Architecture Overview
+----------------------+      +----------------------+
|      Main DB         |      |     Tenant DB(s)     |
| +------------------+ |      | +------------------+ |
| | TenantConfig     | |<---->| | Schema & Data     | |
| +------------------+ |      | +------------------+ |
+----------------------+      +----------------------+
EventDispatcher -> SwitchDbEvent -> TenantEntityManager switches connection
The Symfony Multi-Tenancy Bundle is built on a clear, event-driven architecture that keeps tenant data isolated while sharing a single application codebase.
- Tenant Registry & Configuration
- The Main Database stores a TenantDbConfigentity for each tenant.
- This entity holds connection parameters (host, driver, credentials, schema name) and lifecycle timestamps.
- Dynamic Connection Switching
- At runtime—whether in an HTTP request or console command—you dispatch:
$dispatcher->dispatch(new SwitchDbEvent($tenantId));
- The bundle listens for SwitchDbEvent, resolves the associatedTenantDbConfig, and reconfigures theTenantEntityManagerconnection parameters on the fly.
- Isolated Entity Managers
- Main EntityManager: Manages your global and shared entities (e.g., tenants registry, application settings).
- TenantEntityManager: A separate service injected wherever you need tenant-specific operations. It automatically reconnects to the selected tenant’s database after the event is dispatched.
- Separate Migration & Fixture Paths
- Migrations for the main schema and tenant schemas live in different directories (migrations/Mainvsmigrations/Tenant).
- Fixtures decorated with #[TenantFixture]only run against tenant DBs, ensuring seeding and test data remain isolated.
- Lifecycle & Error Handling
- If a tenant database doesn’t exist, you can enable on-the-fly creation.
- Connection failures throw clear exceptions, allowing you to implement retry logic or fallback strategies.
How to Use This Architecture
- 
Define Your TenantConfig Create an entity in src/Entity/MainimplementingTenantDbConfigurationInterface(use the provided trait for convenience).
- 
Dispatch the Switch Event In controllers or services, dispatch SwitchDbEventbefore any tenant operations:
public function index(EventDispatcherInterface $dispatcher, TenantEntityManager $tem)
{
$dispatcher->dispatch(new SwitchDbEvent($tenantId));
$user = (new User())->setName('Demo');
$tem->persist($user);
$tem->flush();
}
- Manage Migrations & Fixtures
- 
Generate tenant migrations: php bin/console tenant:migration:diff
- 
Apply them: php bin/console tenant:migration:migrate update
- 
Load fixtures: php bin/console tenant:fixtures:load --append
With this architecture, you maintain a single codebase but fully isolated data layers for each tenant, combining the best of multi-tenancy and Symfony’s power.