PHPackages                             wecansync/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. [Framework](/categories/framework)
4. /
5. wecansync/symfony-multi-tenancy-bundle

ActiveSymfony-bundle[Framework](/categories/framework)

wecansync/symfony-multi-tenancy-bundle
======================================

A multi tenancy symfony bundle to support multi-tenant system that works with any symfony project

1.0.1(1y ago)394[2 issues](https://github.com/wecansync/symfony-multitenancy/issues)MITPHPPHP ^8.0|^8.1|^8.2|^8.3

Since Dec 6Pushed 1y ago1 watchersCompare

[ Source](https://github.com/wecansync/symfony-multitenancy)[ Packagist](https://packagist.org/packages/wecansync/symfony-multi-tenancy-bundle)[ RSS](/packages/wecansync-symfony-multi-tenancy-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (9)Versions (2)Used By (0)

multi-tenancy-bundle
====================

[](#multi-tenancy-bundle)

[![sf-multi-tenancy](https://github.com/wecansync/multi-tenancy-bundle/assets/51783676/43351c3d-b947-483f-8c79-b863369ab83d)](https://github.com/wecansync/multi-tenancy-bundle/assets/51783676/43351c3d-b947-483f-8c79-b863369ab83d)

### Packagist Bundle:

[](#packagist-bundle)

A simple method for smoothly integrating multi-tenant databases into your Symfony application is provided by the Symfony Multi Tenancy Bundle. By managing numerous databases through a single entity manager, it facilitates the use of Doctrine and makes runtime switching between databases possible. This package includes a wide range of functionalities, including the simple switching between tenant databases according to an event.

### Numbers:

[](#numbers)

[![Total Downloads](https://camo.githubusercontent.com/98743fb8fc5dac603bca21209b0cccae98b2b0bf89cea20f25da9958895eb3dc/68747470733a2f2f706f7365722e707567782e6f72672f776563616e73796e632f73796d666f6e792d6d756c74692d74656e616e63792d62756e646c652f646f776e6c6f616473)](https://packagist.org/packages/wecansync/symfony-multi-tenancy-bundle)[![Monthly Downloads](https://camo.githubusercontent.com/30f5c1f3d03d7fdaabafad3b3fecde33402d9b1025b334c4316d10e8faba9b24/68747470733a2f2f706f7365722e707567782e6f72672f776563616e73796e632f73796d666f6e792d6d756c74692d74656e616e63792d62756e646c652f642f6d6f6e74686c79)](https://packagist.org/packages/wecansync/symfony-multi-tenancy-bundle)[![Daily Downloads](https://camo.githubusercontent.com/b6c022e38efd2c80c8106bd6dec66e017cdf9afc369f08631d397209e2223d75/68747470733a2f2f706f7365722e707567782e6f72672f776563616e73796e632f73796d666f6e792d6d756c74692d74656e616e63792d62756e646c652f642f6461696c79)](https://packagist.org/packages/wecansync/symfony-multi-tenancy-bundle)

Features:
=========

[](#features)

- Supports all kinds of databases.
- Supports multiple subdomains(tenant1.example.com, tenant2.example.com,..).
- Easy to use and handle
- Extendable bundle
- Not affecting the application performance
- Ability to switch between databases by dispatching a single event
- Ability to auto-generate tenant database using one command
- Ability to auto-generate migrations for each tenant database
- Ability to Seed data into a specific tenant using seed bundle.
- Ability to use messenger to run the processes in background.
- It uses the default entity manager connection.

Requirements:
=============

[](#requirements)

- PHP 8.1+
- Symfony 6+
- Doctrine bundle
- Doctrine Migrations bundle
- Yaml
- Apache
- Virtual host

Installation:
=============

[](#installation)

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

```

Usage:
======

[](#usage)

1. env requirements:
--------------------

[](#1-env-requirements)

- Add `BASE_HOST` to your .env file. Ex: `BASE_HOST=yourmaindomain.com`.

2. Add doctrine connection wrapper
----------------------------------

[](#2-add-doctrine-connection-wrapper)

- open your `config/packages/doctrine.yaml` and add the `wrapper_class````
    # config/packages/doctrine.yaml
    doctrine:
      dbal:
          wrapper_class: WeCanSync\MultiTenancyBundle\DBAL\MultiDbConnectionWrapper

    ```

3. Tenant Entity
----------------

[](#3-tenant-entity)

- Create Tenant Entity or use whatever Entity you want to configure the bundle with:.
- use `TenantConfigTrait` inside your Tenant entity to implement the full db attributes requirements.
- ```
    // src/App/Entity/Tenant
    namespace App\Entity;
    use Doctrine\ORM\Mapping as ORM;
    use WeCanSync\MultiTenancyBundle\Traits\TenantConfigTrait;

    class Tenant
    {
      use TenantConfigTrait;

      #[ORM\Id]
      #[ORM\GeneratedValue]
      #[ORM\Column]
      private ?int $id = null;

    ```

4. Update wecansync\_multi\_tenancy.yaml
----------------------------------------

[](#4-update-wecansync_multi_tenancyyaml)

- Add your Tenant entity path to `config/packages/wecansync_multi_tenancy.yaml` file. ```
      # config/packages/wecansync_multi_tenancy.yaml
      wecansync_multi_tenancy:
        tenant_entity: App\Entity\Tenant # set your custom path for your Tenant entity created in step 2.

    ```

5. Tenant Entity Repository
---------------------------

[](#5-tenant-entity-repository)

- Your `TenantRepository` should impements the `TenantRepositoryInterface` interface. ```
    namespace App\Repository;

    use App\Entity\Tenant;
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Doctrine\Persistence\ManagerRegistry;
    use WeCanSync\MultiTenancyBundle\Model\TenantRepositoryInterface;

    /**
     * @extends ServiceEntityRepository
     */
    class TenantRepository extends ServiceEntityRepository implements TenantRepositoryInterface{

    // your custom functions here

    ```
- Define `findBySubdomain` and `findByIdentifier` functions in your repository ```
    public function findBySubdomain($subdomain){
        // subdomain is required here
        // you can add your specific filters here like "status","isActive",...
        return $this->findOneBy(["subdomain" => $subdomain]);
    }

    public function findByIdentifier($identifier){
        // use your identifier (unique value) or whathever you want(email, username,id,...)
        return $this->findOneBy(["yourCustomIdentifier" => $identifier]);
    }

    ```

6. Create first migration
-------------------------

[](#6-create-first-migration)

- create db migration using this command: ```
    bin/console doctrine:migrations:diff // default migrations folder is '%kernel.project_dir%/migrations'

    ```
- update db schema using this command: ```
    bin/console doctrine:migrations:migrate

    ```
- you can update your migrations folder by editing `doctrine_migrations.yaml````
      # config/packages/doctrine_migrations.yaml
      doctrine_migrations:
        migrations_paths:
            # namespace is arbitrary but should be different from App\Migrations
            # as migrations classes should NOT be autoloaded
            'DoctrineMigrations\Main': '%kernel.project_dir%/migrations/main'
        enable_profiler: '%kernel.debug%'

    ```

7. Using evotodi/seed-bundle (optional)
---------------------------------------

[](#7-using-evotodiseed-bundle-optional)

- follow this documentation to create a Seed class:
- update you Seed class as following to create seeds for your tenant databases ```
      namespace App\Seeds;
      /**
      * The load method is called when loading a seed
      */
      public function load(InputInterface $input, OutputInterface $output): int
      {

          /**
          * Doctrine logging eats a lot of memory, this is a wrapper to disable logging
          */
          $this->disableDoctrineLogging();

          /** @var MultiDbConnectionWrapper $connection */
          $connection = $this->em->getConnection();

          $this->runSeeds(); // run your seeds for your main database; you should define the runSeeds() function before.

          $tenants = $this->getTenants(); // add a function to fetch tenants from your main database.

          if (!count($tenants)) {
              return 0;
          }

          // loading seeds for each tenant
          foreach ($tenants as $tenant) {
              try {
                  $connection->changeDatabase($tenant->getDbName());
                  $this->runSeeds();
              } catch (Exception $e) {
                  // error handling here
              }
          }

          /**
          * Must return an exit code.
          * A value other than 0 or Command::SUCCESS is considered a failed seed load/unload.
          */
          return 0;
      }

    ```

8. Create tenant instance and database
--------------------------------------

[](#8-create-tenant-instance-and-database)

- create a record in your tenant entity (email, name, subdomain, dbName): ```
      $tenant = new Tenant();
      $tenant->setEmail("email@example.com");
      $tenant->setName("First tenant");
      $tenant->setSubdomain("first");
      $tenant->setDbName("tenant_1");
      $em->persist($tenant);
      $em->flush();

    ```
- use this command to create a database for a specific tenant ```
      php bin/console tenant:database:create

    ```
- You will be prompted to enter the tenant identifier(username|id|email|..)

9. Add RouterSubscriber class to your project (optional)
--------------------------------------------------------

[](#9-add-routersubscriber-class-to-your-project-optional)

- Define a class that implements `EventSubscriberInterface` in order to switch between databases automatically based on subdomain assigned to a specific Tenant ```
    // src/EventSubscriber/RouterSubscriber.php
    namespace App\EventSubscriber;

    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\HttpKernel\Event\ControllerEvent;

    use WeCanSync\MultiTenancyBundle\Service\TenantService;

    class RouterSubscriber implements EventSubscriberInterface
    {
        public function __construct(
            // inject the TenantService in your constructor
            private TenantService $tenantService
            )
        {
        }
        public static function getSubscribedEvents()
        {
            return array(
                KernelEvents::CONTROLLER => array(array('onKernelController', 1)),
            );
        }

        public function onKernelController(ControllerEvent $event)
        {
          $request = $event->getRequest();

          // call the checkCurrentTenant function to detect the domain changes and switch to the tenant's specific database.
          $this->tenantService->checkCurrentTenant($request);
        }
    }

    ```

10. Manually switch between databases (optional)
------------------------------------------------

[](#10-manually-switch-between-databases-optional)

- you can manually switch between databases by calling this function ```
    // $em is the main entity manager
    $connection = $em->getConnection();
    $connection->changeDatabase("your database name");

    ```

Other Instructions will be added soon.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance26

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

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

Unknown

Total

1

Last Release

521d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/0fa3e9c0449cddc89a808ae79cbd9f59cfd8f25b16927976919457a73ba0d4f4?d=identicon)[fouadSalkini](/maintainers/fouadSalkini)

![](https://www.gravatar.com/avatar/3d6e7197a18c4e80df5d483582faf205122d61002f6abfde5d1970479bc7b8db?d=identicon)[icemaker](/maintainers/icemaker)

---

Top Contributors

[![fouadSalkini](https://avatars.githubusercontent.com/u/51783676?v=4)](https://github.com/fouadSalkini "fouadSalkini (6 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[symfony/framework-bundle

Provides a tight integration between Symfony components and the Symfony full-stack framework

3.6k235.4M9.7k](/packages/symfony-framework-bundle)[sylius/sylius

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

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

EC-CUBE EC open platform.

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

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

1.3k1.3M152](/packages/sulu-sulu)[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)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k16.7M310](/packages/easycorp-easyadmin-bundle)

PHPackages © 2026

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