PHPackages                             apajo/symfony-multi-tenancy-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. apajo/symfony-multi-tenancy-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

apajo/symfony-multi-tenancy-bundle
==================================

Symfony multi tenancy bundle

0.6.12(1y ago)41.5k↑150%[1 issues](https://github.com/apajo/symfony-multi-tenancy-bundle/issues)MITPHPPHP ^8.2

Since Jun 11Pushed 1y ago1 watchersCompare

[ Source](https://github.com/apajo/symfony-multi-tenancy-bundle)[ Packagist](https://packagist.org/packages/apajo/symfony-multi-tenancy-bundle)[ Docs](https://www.apajo.ee)[ RSS](/packages/apajo-symfony-multi-tenancy-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (16)Versions (49)Used By (0)

Symfony Multi Tenancy Bundle
============================

[](#symfony-multi-tenancy-bundle)

Description
-----------

[](#description)

There are many packages that provide multi tenancy in Symfony. All of them provide only different database configuration per tenant.

This package's goal is to provide a way to manage any kind of configuration in your system.

This bundle aims to provide multi tenancy on a higher level. It provides a way to dynamically change the system configuration based on the tenant (database, media provider, mailer etc).

It also bundles a way to manage migrations for each tenant.

The package's development is in early stages, any feedback is welcome.

Requirements
------------

[](#requirements)

- [Symfony 6.4 / 7.1](https://www.symfony.com/)
- [Doctrine Bundle 2.12](https://github.com/doctrine/DoctrineBundle.git)
- [Doctrine Migrations Bundle 3.3](https://github.com/doctrine/migrations.git)
- [Symfony Security Bundley](https://symfony.com/components/Security%20Bundle)
- [PHP 8.2](https://www.php.com/)

Installation
============

[](#installation)

Make sure Composer is installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md)of the Composer documentation.

Applications that use Symfony Flex
----------------------------------

[](#applications-that-use-symfony-flex)

Open a command console, enter your project directory and execute:

```
composer require apajo/symfony-multi-tenancy-bundle
```

Applications that don't use Symfony Flex
----------------------------------------

[](#applications-that-dont-use-symfony-flex)

### Step 1: Download the Bundle

[](#step-1-download-the-bundle)

Open a command console, enter your project directory and execute the following command to download the latest stable version of this bundle:

```
composer require apajo/symfony-multi-tenancy-bundle
```

### Step 2: Enable the Bundle

[](#step-2-enable-the-bundle)

Then, enable the bundle by adding it to the list of registered bundles in the `config/bundles.php` file of your project:

```
// config/bundles.php

return [
    // ...
    aPajo\MultiTenancyBundle\APajoMultiTenancyBundle::class => ['all' => true],
];
```

Configuration
-------------

[](#configuration)

To change your

### doctrine.yml

[](#doctrineyml)

You need 2 connections and entity\_managers:

```
doctrine:
  dbal:
    default_connection: default
    connections:
      default:
        url: '%env(DEFAULT_DATABASE_URL)%'
        driver: pdo_mysql
        charset: utf8
        server_version: '8'

      tenant:
        url: '%env(TENANT_DATABASE_URL)%'
        driver:   pdo_mysql
        charset:  utf8
        server_version: '8'

  orm:
    default_entity_manager: default
    auto_generate_proxy_classes: true

    entity_managers:
      default:
        connection: default
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware

      tenant:
        connection: tenant
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
        mappings:
```

In this case thay are named `default` and `tenant` but you can name them as you wish.

> **NB!** Third party packages may require the `default` connection to be present so you might want to keep the `default` name.

Connection and entity manager `default` are common for all the individual tenants. Connection and entity manager `tenant` are specific for the tenant.

apajo\_multi\_tenancy.yml
-------------------------

[](#apajo_multi_tenancyyml)

```
apajo_multi_tenancy:
  adapters: # Adapters dynamically change the system configuration for selected tenant
    - aPajo\MultiTenancyBundle\Adapter\Database\DatabaseAdapter
    - aPajo\MultiTenancyBundle\Adapter\Filesystem\FilesystemAdapter
    - aPajo\MultiTenancyBundle\Adapter\Mailer\MailerAdapter

  tenant:                                   # Tenant (entity) configuration
    class: App\Entity\Tenant                # Must implement TenantInterface
    identifier: key                         # Identifier column name (must be unique field)
    entity_manager: default                 # Tenant entity manager name
    resolvers:                              # Resolvers resolve the tenant based on the request
      - aPajo\MultiTenancyBundle\Service\Resolver\HostBasedResolver

  migrations: # Tenant Migration configurations
    default: 'config/migrations/default.yml'
    tenant: 'config/migrations/tenant.yml'
```

services.yml
------------

[](#servicesyml)

Every adapter you use must be registered as a service. Example of the built-in ones:

```
services:
  # ...

  aPajo\MultiTenancyBundle\Adapter\Filesystem\FilesystemAdapter:
    arguments:
      - '@sonata.media.adapter.filesystem.local' # sonata.media.adapter.filesystem.ftp

  aPajo\MultiTenancyBundle\Adapter\Mailer\MailerAdapter:
    tags:
      - { name: mailer.transport_factory }

  aPajo\MultiTenancyBundle\Adapter\Database\DatabaseAdapter:
    arguments:
      $doctrine: '@doctrine'

  # ...
```

### Doctrine migrations configuration

[](#doctrine-migrations-configuration)

Recommended path for the configuration files is `config/migrations/`.

#### default.yml

[](#defaultyml)

```
migrations_paths:
  'App\Migrations\Default': 'migrations/default'
```

#### tenant.yml

[](#tenantyml)

```
migrations_paths:
  'App\Migrations\Tenant': 'migrations/tenant'
```

Adapters
--------

[](#adapters)

Adapters are responsible for dynamic configuration changes based on tenant table values at runtime.

For more on (built-in) adapters see [Adapters directory](./src/Adapter/README.md)

Resolvers
---------

[](#resolvers)

Resolvers are responsible for resolving current tenant.

For more on (built-in) resolvers see [Resolvers directory](./src/Service/Resolver/README.md)

Database migrations
-------------------

[](#database-migrations)

This bundle adds just 2 new commands to your project:

```
# Create new migrations/diffs (for default and tenant connections)

php bin/console tenants:migrations:diff
```

```
# Apply migrations to the tenants (or a single tenant) and the default connection

php bin/console tenants:migrations:migrate [tenant_id]
```

**NB!** All other migration commands are as-is by [DoctrineMigrationsBundle](https://symfony.com/bundles/DoctrineMigrationsBundle/current/index.html)

Examples
--------

[](#examples)

### Switch/select tenant

[](#switchselect-tenant)

```
use aPajo\MultiTenancyBundle\Service\EnvironmentProvider;
use aPajo\MultiTenancyBundle\Entity\TenantInterface;
use aPajo\MultiTenancyBundle\Event\TenantSelectEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface

class Tenant implements TenantInterface {
    // ...
}

class MyTenantSelectService {
  public function __construct (
    private EnvironmentProvider $environmentProvider,
    private EventDispatcherInterface $dispatcher,
  ) {
  }

  /**
   * Use the EnvironmentProvider to select a different tenant
   */
  public function select () {
    $tenant = new Tenant();

    $environmentProvider->select($tenant);
    // Now the system is configured based on the tenant
  }

  /**
   * You can also dispatch an event to select a new tenant
   */
  public function alternativeSelect () {
      $tenant = new Tenant();

      $event = new TenantSelectEvent($tenant);
      $this->dispatcher->dispatch($event);
  }
}
```

### Iterate over all tenant environments

[](#iterate-over-all-tenant-environments)

```
use aPajo\MultiTenancyBundle\Service\EnvironmentProvider;
use aPajo\MultiTenancyBundle\Entity\TenantInterface;

class MyTenantService {
  public function __construct (
    private EnvironmentProvider $environmentProvider,
  ) {

    $environmentProvider->forAll(function (TenantInterface $tenant) {
      // Each iteration will have tenant specific configuration/environment
    });

  }

}
```

Development
-----------

[](#development)

### Testing

[](#testing)

```
./vendor/bin/simple-phpunit
```

Issues
------

[](#issues)

Feel free to report an issue [under GitHub Issues](https://github.com/apajo/symfony-multi-tenancy-bundle/issues)

### Known Issues

[](#known-issues)

- Resetting to default/initial tenant does not work
- Symfony profiler currently shows only default entity managers migrations

Contributing
------------

[](#contributing)

Feel free to [contribute](https://github.com/apajo/symfony-multi-tenancy-bundle/pulls)

### Versioning

[](#versioning)

Versions must be numbered following the [Semantic Versioning Specification](https://semver.org/).

### Packagist

[](#packagist)

Packagist [link](https://packagist.org/packages/apajo/symfony-multi-tenancy-bundle)

### Thanks to

[](#thanks-to)

This bundle is inspired by the [RamyHakam / multi\_tenancy\_bundle](https://github.com/RamyHakam/multi_tenancy_bundle)

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance38

Infrequent updates — may be unmaintained

Popularity23

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Total

47

Last Release

448d ago

PHP version history (2 changes)0.0.2PHP ^8.1

0.0.15PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/37815dfa89cf128acb1f61419ae926f9aeb8c93c3261e90df6a3d52df51dc22b?d=identicon)[aPajo](/maintainers/aPajo)

---

Top Contributors

[![apajo](https://avatars.githubusercontent.com/u/3619593?v=4)](https://github.com/apajo "apajo (76 commits)")

---

Tags

symfonydoctrinesaasmulti-tenancytenantsDynamic tenant configurationSoftware-as-a-ServiceHost based multi tenancy

###  Code Quality

TestsPHPUnit

Static AnalysisRector

### Embed Badge

![Health badge](/badges/apajo-symfony-multi-tenancy-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/apajo-symfony-multi-tenancy-bundle/health.svg)](https://phpackages.com/packages/apajo-symfony-multi-tenancy-bundle)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[kimai/kimai

Kimai - Time Tracking

4.6k7.4k1](/packages/kimai-kimai)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

7310.3k29](/packages/open-dxp-opendxp)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
