A comprehensive demonstration of multi-tenancy patterns using the Zhortein Multi-Tenant Bundle for Symfony 7+.
This application showcases how to implement multi-tenancy in a Symfony application where multiple organizations (tenants) can use the same application instance while maintaining complete data isolation. Each tenant has their own isolated data space while sharing the same codebase and infrastructure.
- Path-based tenant resolution (
/tenant-slug/...) - Automatic data isolation using tenant-aware entities
- Shared database with tenant filtering
- Complete tenant context management
- Tenant Management: Create, edit, and manage tenants
- Product Catalog: Tenant-specific product management
- User Management: Tenant-scoped user accounts
- Admin Dashboard: System-wide administration
- Tenant Dashboards: Individual tenant analytics
- PHP 8.3+ with strict typing
- Symfony 7.0+ following best practices
- PostgreSQL 16 with Doctrine ORM
- Bootstrap 5 responsive UI
- Docker containerization
- PHPStan Level Max compliance
- Docker & Docker Compose
- PHP 8.3+ (for local development)
- PostgreSQL 16 (handled by Docker)
- Clone and setup the project:
git clone <repository-url> multi-tenant-demo
cd multi-tenant-demo- Start the Docker environment:
docker compose up -d- Install dependencies:
docker compose exec php composer install- Setup the database:
docker compose exec php php bin/console doctrine:migrations:migrate --no-interaction- Create sample data:
docker compose exec php php bin/console app:create-sample-data- Access the application:
- Homepage: https://drenard.devlogiciel.com/
- Admin Dashboard: https://drenard.devlogiciel.com/admin
Tenant (TenantInterface)
βββ Users (TenantAware)
βββ Products (TenantAware)
βββ ... other tenant-specific entities
Tenant: ImplementsTenantInterface, represents organizationsUser: Tenant-aware user entity with authenticationProduct: Tenant-aware product catalog entity
DashboardController: Main application entry pointsTenantController: Admin tenant managementProductController: Tenant-specific product management
- Bundle Configuration:
config/packages/zhortein_multi_tenant.yaml - Tenant Resolution: Path-based (
/{tenantSlug}/...) - Data Isolation: Automatic filtering via
@TenantAwareattribute
Visit the homepage to see all available tenants and choose one to explore.
Each tenant has isolated access:
- Acme Corp:
/acme-corp/products - Global Retail:
/global-retail/products - TechStart:
/techstart/products
System administrators can:
- View all tenants:
/admin/tenants - Create new tenants:
/admin/tenants/new - Monitor system-wide statistics:
/admin
- Products created in one tenant are invisible to others
- Users belong to specific tenants
- Database queries are automatically filtered
# config/packages/zhortein_multi_tenant.yaml
zhortein_multi_tenant:
tenant_entity: App\Entity\Tenant
resolution:
strategy: path
parameter_name: tenantSlug
context:
auto_set: true# config/packages/doctrine.yaml
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
server_version: '16'
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: trueThe application includes three pre-configured tenants:
- Focus: Technology solutions
- Products: Smart widgets, connectors, security modules
- Users: 3 sample users
- Focus: Retail and fashion
- Products: Clothing, shoes, accessories
- Users: 3 sample users
- Focus: Software development tools
- Products: Code editors, APIs, monitoring tools
- Users: 3 sample users
- Create the entity:
<?php
namespace App\Entity;
use App\Entity\Tenant;
use Doctrine\ORM\Mapping as ORM;
use Zhortein\MultiTenantBundle\Attribute\TenantAware;
#[ORM\Entity]
#[TenantAware(tenantFieldName: 'tenant')]
class YourEntity
{
#[ORM\ManyToOne(targetEntity: Tenant::class)]
#[ORM\JoinColumn(nullable: false)]
private Tenant $tenant;
// ... other properties
}- The bundle automatically handles:
- Tenant context injection
- Query filtering
- Data isolation
docker compose exec php php bin/phpunit# PHPStan analysis
docker compose exec php vendor/bin/phpstan analyse
# PHP CS Fixer
docker compose exec php vendor/bin/php-cs-fixer fixGET /- Homepage with tenant selectionGET /admin- Admin dashboardGET /admin/tenants- Tenant management
GET /{tenantSlug}- Tenant dashboardGET /{tenantSlug}/products- Product listingPOST /{tenantSlug}/products- Create productGET /{tenantSlug}/products/{id}- Product details
- Automatic filtering: All queries are automatically scoped to the current tenant
- Context validation: Tenant context is validated on each request
- Cross-tenant protection: Users cannot access other tenants' data
- Users are scoped to their tenant
- Admin access is separate from tenant access
- CSRF protection on all forms
- Database indexing on tenant foreign keys
- Query optimization with automatic tenant filtering
- Caching strategies for tenant resolution
- Lazy loading for related entities
- Tenant-specific analytics in dashboards
- System-wide statistics for administrators
- Performance metrics per tenant
- Configure environment variables
- Set up SSL certificates
- Configure database connection
- Run migrations
- Set up monitoring
- Configure backup strategy
DATABASE_URL=postgresql://user:pass@localhost:5432/db_name
APP_ENV=prod
APP_SECRET=your-secret-key- Fork the repository
- Create a feature branch
- Follow PSR-12 coding standards
- Add tests for new functionality
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- Zhortein Multi-Tenant Bundle - The core multi-tenancy functionality
- Symfony Framework - The robust foundation
- Bootstrap - The responsive UI framework
- Docker - Containerization platform
For questions about this demo application:
- Create an issue in the repository
- Check the Zhortein Multi-Tenant Bundle documentation
- Review Symfony best practices documentation
Built with β€οΈ using Symfony 7+ and the Zhortein Multi-Tenant Bundle