hakam / multi-tenancy-bundle
Flexible and production-ready multi-tenancy bundle for Symfony.
Package info
github.com/RamyHakam/multi_tenancy_bundle
Type:symfony-bundle
pkg:composer/hakam/multi-tenancy-bundle
Requires
- php: ^8.1
- doctrine/doctrine-bundle: ^2.7
- doctrine/doctrine-migrations-bundle: ^3.0
- doctrine/orm: ^2.15 || ^3.0
- psr/cache: ^3.0
- symfony/cache-contracts: ^3.0
- symfony/config: ^6.4|^7.0
- symfony/dependency-injection: ^6.4|^7.0
- symfony/filesystem: ^6.4|^7.0
- symfony/http-kernel: ^6.4|^7.0
- symfony/var-exporter: ^6.4|^7.0|^8.0
Requires (Dev)
- dg/bypass-finals: ^1.9
- doctrine/doctrine-fixtures-bundle: ^3.6
- phpunit/phpunit: ^10.0
- symfony/phpunit-bridge: ^6.4|^7.0
This package is auto-updated.
Last update: 2026-05-26 17:16:27 UTC
README
📚 Full Documentation: Documentation
🧩 Overview
The Symfony Multi-Tenancy Bundle enables scalable, production-ready multi-tenancy for Symfony applications.
Ideal for SaaS platforms, region-based services, and multi-vendor e-commerce systems, this bundle is built around a database-per-tenant architecture, giving each tenant:
- A fully isolated database
- Independent schema and migrations
- Configurable connection parameters (host, driver, credentials)
It integrates seamlessly with Doctrine and Symfony's service container, offering:
- Automatic tenant database switching at runtime via
SwitchDbEvent - Automatic tenant resolution from HTTP requests (subdomain, path, header, or custom)
- Separate migration and fixture paths for main vs. tenant databases
- Dedicated
TenantEntityManagerservice for runtime isolation
For full usage examples and advanced configuration, see the documentation.
🔄 Automatic Tenant Resolution (v3.0.0+)
Automatically resolve the current tenant from incoming HTTP requests — no manual event dispatching required.
Supported Strategies
| Strategy | Example | Description |
|---|---|---|
subdomain |
tenant1.example.com |
Extracts tenant from subdomain |
path |
/tenant1/dashboard |
Extracts tenant from URL path segment |
header |
X-Tenant-ID: tenant1 |
Extracts tenant from HTTP header |
host |
client.com → tenant1 |
Maps full hostname to tenant |
chain |
Multiple strategies | Tries resolvers in order with fallback |
Quick Configuration
# config/packages/hakam_multi_tenancy.yaml hakam_multi_tenancy: resolver: enabled: true strategy: subdomain # subdomain | path | header | host | chain options: base_domain: 'example.com' # for subdomain strategy
Strategy Examples
Subdomain-based (e.g., acme.myapp.com):
resolver: enabled: true strategy: subdomain options: base_domain: 'myapp.com'
Header-based (for APIs):
resolver: enabled: true strategy: header options: header_name: 'X-Tenant-ID'
Path-based (e.g., /acme/dashboard):
resolver: enabled: true strategy: path excluded_paths: ['/api/public', '/health']
Chain strategy (fallback support):
resolver: enabled: true strategy: chain options: chain_order: [header, subdomain, path]
Accessing Resolved Tenant
The resolved tenant ID is available in request attributes:
// In a controller $tenantId = $request->attributes->get('_tenant');
Custom Resolver
Implement TenantResolverInterface for custom logic:
use Hakam\MultiTenancyBundle\Port\TenantResolverInterface; class CustomResolver implements TenantResolverInterface { public function resolve(Request $request): ?string { // Your custom logic return $request->cookies->get('tenant_id'); } public function supports(Request $request): bool { return $request->cookies->has('tenant_id'); } }
Note: Automatic resolution is disabled by default for backward compatibility. Manual
SwitchDbEventdispatching continues to work.
🚀 Quick Installation
1. Via Symfony Flex (Recommended)
composer require hakam/multi-tenancy-bundle
Symfony Flex will automatically scaffold config, register the bundle, and create:
src/Entity/Main/
src/Entity/Tenant/
migrations/Main/
migrations/Tenant/
2. Manual Installation
composer require hakam/multi-tenancy-bundle
Then register in config/bundles.php, copy the example hakam_multi_tenancy.yaml from docs, and create the required directories.
📖 Examples
The examples/ directory contains 15 ready-to-use code examples covering every feature of the bundle:
| # | Example | Feature |
|---|---|---|
| 01 | Entity Setup | TenantDbConfig entity with TenantDbConfigTrait |
| 02 | Bundle Configuration | Full YAML config reference |
| 03 | Tenant Entities | Tenant-scoped entities (Product, Order) |
| 04 | Database Lifecycle | Create DB, switch, CRUD, CLI commands |
| 05 | Tenant Migrations | Platform-agnostic migrations with Schema API |
| 06 | Resolvers | All 5 resolution strategies + controller usage |
| 07 | Lifecycle Events | All 6 events with subscriber pattern |
| 08 | Custom Config Provider | Redis, static, and in-memory providers |
| 09 | Tenant Fixtures | #[TenantFixture] attribute + CLI |
| 10 | Cache Isolation | TenantAwareCacheDecorator usage |
| 11 | Tenant Context | TenantContextInterface in services, Twig, listeners |
| 12 | Testing | TenantTestTrait with runInTenant() |
| 13 | Shared Entities | #[TenantShared] with exclusions |
| 14 | Custom Resolver | JWT, query param, API key resolvers |
| 15 | Full Onboarding Flow | Complete end-to-end tenant onboarding |
See also the Examples documentation page for detailed explanations.
🔗 Useful Links
- Full Documentation: [https://ramyhakam.github.io/multi_tenancy_bundle/]
- GitHub: https://github.com/RamyHakam/multi_tenancy_bundle
- Packagist: https://packagist.org/packages/hakam/multi-tenancy-bundle
- Example Project: https://github.com/RamyHakam/multi-tenancy-project-example
📄 License
MIT © Ramy Hakam