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.

dev-main 2025-08-05 12:35 UTC

This package is auto-updated.

Last update: 2025-08-05 12:35:43 UTC


README

A comprehensive Symfony 7+ bundle for building multi-tenant applications with PostgreSQL 16 support.

PHP Version Symfony Version PostgreSQL Version

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, Messenger, and file storage integration
  • ๐ŸŽฏ Event-Driven: Database switching events and automatic tenant context resolution
  • ๐Ÿ› ๏ธ Advanced Commands: Schema management, migrations, and fixtures for tenants
  • ๐Ÿงช Fully Tested: Comprehensive test suite with PHPUnit 12
  • ๐Ÿ“Š 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

๐Ÿ—๏ธ Core Concepts

๐Ÿ”ง Service Integration

  • Mailer - Tenant-aware email with templated support
  • Messenger - Tenant-aware queues with transport routing
  • Storage - File storage isolation

๐Ÿ—„๏ธ Database Management

๐Ÿ› ๏ธ Development Tools

๐Ÿ“– Examples

Testing

Run the test suite using the Makefile:

# Run all tests
make test

# Run unit tests only
make test-unit

# Run integration tests only
make test-integration

# Run with coverage
make test-coverage

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

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for your changes
  4. Ensure all tests pass and code meets quality standards
  5. 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

Changelog

See CHANGELOG.md for version history and upgrade instructions.