zhortein/multi-tenant-bundle
Composer 安装命令:
composer require zhortein/multi-tenant-bundle
包简介
A comprehensive Symfony 7+ bundle for building multi-tenant applications with PostgreSQL 16 support, featuring multiple resolution strategies, tenant-aware services, and automatic database filtering.
关键字:
README 文档
README
A comprehensive Symfony 7+ bundle for building multi-tenant applications with PostgreSQL 16 support.
Features
- 🏢 Multiple Tenant Resolution Strategies: Subdomain, path-based, header-based, domain-based, DNS TXT, hybrid, or custom resolvers
- 🗄️ Database Strategies: Shared database with filtering or separate databases per tenant
- ⚡ Performance Optimized: Built-in caching for tenant settings and configurations
- 🔧 Doctrine Integration: Automatic tenant filtering with Doctrine ORM
- 📧 Tenant-Aware Services: Mailer with automatic tenant propagation, Messenger with context preservation, and file storage integration
- 🎯 Event-Driven: Database switching events and automatic tenant context resolution
- 🛠️ Advanced Commands: Schema management, migrations, and fixtures for tenants
- 🧪 Comprehensive Test Kit: First-class testing utilities to prove tenant isolation works
- 🔒 RLS Integration: PostgreSQL Row-Level Security for defense-in-depth
- 📊 PHPStan Level Max: Static analysis at maximum level
Installation
Install the bundle via Composer:
composer require zhortein/multi-tenant-bundle
Enable the bundle in your config/bundles.php:
<?php return [ // ... Zhortein\MultiTenantBundle\ZhorteinMultiTenantBundle::class => ['all' => true], ];
Quick Start
1. Create Your Tenant Entity
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Zhortein\MultiTenantBundle\Entity\TenantInterface; #[ORM\Entity] #[ORM\Table(name: 'tenants')] class Tenant implements TenantInterface { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 255, unique: true)] private string $slug; #[ORM\Column(type: 'string', length: 255)] private string $name; // Implement TenantInterface methods... public function getId(): ?int { return $this->id; } public function getSlug(): string { return $this->slug; } public function setSlug(string $slug): void { $this->slug = $slug; } // ... other methods }
2. Configure the Bundle
Create config/packages/zhortein_multi_tenant.yaml:
zhortein_multi_tenant: tenant_entity: 'App\Entity\Tenant' resolver: type: 'subdomain' options: base_domain: 'example.com' database: strategy: 'shared_db' enable_filter: true
3. Create Tenant-Aware Entities
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Zhortein\MultiTenantBundle\Attribute\AsTenantAware; use Zhortein\MultiTenantBundle\Entity\TenantAwareEntityTrait; #[ORM\Entity] #[AsTenantAware] class Product { use TenantAwareEntityTrait; #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\Column(type: 'string', length: 255)] private string $name; // ... other properties and methods }
4. Use in Controllers
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Zhortein\MultiTenantBundle\Context\TenantContextInterface; class DashboardController extends AbstractController { public function index(TenantContextInterface $tenantContext): Response { $tenant = $tenantContext->getTenant(); // All database queries are automatically filtered by tenant $products = $this->entityManager ->getRepository(Product::class) ->findAll(); // Only returns current tenant's products return $this->render('dashboard/index.html.twig', [ 'tenant' => $tenant, 'products' => $products, ]); } }
📚 Documentation
🚀 Getting Started
- Installation & Setup - Complete installation guide
- Configuration Reference - All configuration options
- Database Strategies - Shared DB vs Multi-DB
🏗️ Core Concepts
- Tenant Context - Tenant resolution and access
- Tenant Resolution - Resolution strategies
- DNS TXT Resolver - DNS-based tenant resolution
- Domain Resolvers - Domain and hybrid resolvers
- Doctrine Tenant Filter - Automatic filtering
- Tenant Settings - Configuration system
🔧 Service Integration
- Mailer - Tenant-aware email with templated support
- Messenger - Tenant-aware queues with automatic context propagation
- Storage - File storage isolation
🗄️ Database Management
- Migrations - Database migrations
- Fixtures - Test data loading
🛠️ Development Tools
- CLI Commands - Console commands
- Testing - Testing strategies and Test Kit
- FAQ - Common questions
📖 Examples
- Basic Usage - Code examples
- Mailer Examples - Email templates and configuration
- Messenger Examples - Message routing and handling
- Service Integration - Practical implementations
Testing with the Bundle
The bundle includes a comprehensive Test Kit to make testing multi-tenant applications easy and reliable:
Test Kit Features
- WithTenantTrait: Execute code within specific tenant contexts
- TestData: Lightweight builders for tenant-aware test entities
- Base Test Classes: Pre-configured for HTTP, CLI, and Messenger testing
- RLS Isolation Tests: Prove PostgreSQL Row-Level Security works as defense-in-depth
Quick Example
<?php use Zhortein\MultiTenantBundle\Tests\Toolkit\TenantWebTestCase; class ProductControllerTest extends TenantWebTestCase { public function testTenantIsolation(): void { // Seed test data $this->getTestData()->seedProducts('tenant-a', 2); $this->getTestData()->seedProducts('tenant-b', 1); // Test tenant A sees only its data $this->withTenant('tenant-a', function () { $products = $this->repository->findAll(); $this->assertCount(2, $products); }); // Test RLS isolation (critical test) $this->withTenant('tenant-a', function () { $this->withoutDoctrineTenantFilter(function () { $products = $this->repository->findAll(); // Should still see only 2 products due to RLS $this->assertCount(2, $products); }); }); } }
Running Tests
# Run all tests make test # Run unit tests only make test-unit # Run integration tests only make test-integration # Run Test Kit RLS isolation tests vendor/bin/phpunit tests/Integration/RlsIsolationTest.php # Run with coverage make test-coverage
See the Testing Documentation for complete Test Kit usage.
Code Quality
# PHPStan at maximum level make phpstan # PHP-CS-Fixer code style check make csfixer-check # Fix code style make csfixer # Run all quality checks make dev-check
Contributing
- Fork the repository
- Create a feature branch
- Write tests for your changes
- Ensure all tests pass and code meets quality standards
- Submit a pull request
See CONTRIBUTING.md for detailed guidelines.
License
This bundle is released under the MIT License. See the LICENSE file for details.
Support
- Documentation: Complete documentation
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Changelog
See CHANGELOG.md for version history and upgrade instructions.
统计信息
- 总下载量: 30
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 3
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-08-04