PHPackages                             nubitio/tenant-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. nubitio/tenant-bundle

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

nubitio/tenant-bundle
=====================

Opt-in column-tenant kit for Nubit Symfony apps: TenantScoped attribute, Doctrine filter, context resolver, and registry.

v0.10.3(today)01↑2900%MITPHPPHP &gt;=8.5

Since Jun 19Pushed todayCompare

[ Source](https://github.com/nubitio/tenant-bundle)[ Packagist](https://packagist.org/packages/nubitio/tenant-bundle)[ Docs](https://github.com/nubitio/nubit-symfony/tree/main/packages/tenant-bundle)[ RSS](/packages/nubitio-tenant-bundle/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (12)Versions (5)Used By (0)

@nubitio/tenant-bundle
======================

[](#nubitiotenant-bundle)

Opt-in multi-tenancy for Nubit Symfony apps: **column mode** (shared DB + Doctrine filter) or **database mode** (per-tenant DSN), plus optional plan quota enforcement.

Install
-------

[](#install)

```
composer require nubitio/tenant-bundle
```

Register the bundle and enable it when the app profile is `saas` or `hybrid`:

```
# config/packages/nubit_tenant.yaml
nubit_tenant:
    enabled: true
    isolation: column          # column | database
    resolution: [user, jwt_claim]
    tenant_entity: App\Entity\Restaurant   # or omit for Nubit\TenantBundle\Entity\Tenant
    quotas_enabled: false      # set true to enforce plan limits on prePersist
    rls_enabled: false
```

Pair with admin-bundle SaaS profile:

```
# config/packages/nubit_admin.yaml
nubit_admin:
    app_profile: saas
    single_tenant_defaults: false
```

Column isolation (default)
--------------------------

[](#column-isolation-default)

Mark tenant-owned entities with `#[TenantScoped]` and implement `TenantOwnedInterface`. The Doctrine `nubit_tenant` filter scopes queries to the active tenant.

```
use Nubit\TenantBundle\Attribute\TenantScoped;
use Nubit\TenantBundle\Contract\TenantOwnedInterface;
use Nubit\TenantBundle\Entity\TenantOwnedTrait;

#[TenantScoped]
#[ORM\Entity]
class Order implements TenantOwnedInterface
{
    use TenantOwnedTrait;
}
```

Custom column + association stamping (RestoPOS pattern):

```
#[TenantScoped(field: 'restaurant_id', relation: 'restaurant')]
class Order implements RestaurantOwnedInterface
{
    use RestaurantOwnedTrait;
}
```

Users should implement `TenantAwareUserInterface` so the `user` resolver can populate `TenantContext`.

Database isolation
------------------

[](#database-isolation)

Switch `isolation: database` to route each request to a tenant-specific database URL. The control-plane registry (same `tenant_entity`) must expose `getDatabaseUrl()`:

```
nubit_tenant:
    enabled: true
    isolation: database
    tenant_connection: default
    control_plane_connection: default
```

Configure the tenant connection wrapper:

```
# config/packages/doctrine.yaml
doctrine:
    dbal:
        connections:
            default:
                wrapper_class: Nubit\TenantBundle\Doctrine\Connection\DynamicUrlConnection
```

The default `Nubit\TenantBundle\Entity\Tenant` ships `isolationMode` and `databaseUrl` columns. Custom tenant entities (e.g. `Restaurant`) must add equivalent fields and `getDatabaseUrl()`.

Plan quotas
-----------

[](#plan-quotas)

Enable `quotas_enabled: true` to block `prePersist` when a plan limit is reached. Limits come from `FeatureCheckerInterface::getFeatureConfig($resource)['max']`.

1. Tag entities with the quota resource name:

```
use Nubit\TenantBundle\Attribute\QuotaResource;

#[QuotaResource('team_users')]
#[ORM\Entity]
class User { /* … */ }
```

2. Register usage counters via `QuotaUsageProviderInterface` (autoconfigured with tag `nubit.quota_usage_provider`):

```
final readonly class TeamUsersQuotaUsageProvider implements QuotaUsageProviderInterface
{
    public function supports(string $resource): bool
    {
        return 'team_users' === $resource;
    }

    public function count(string $resource): int
    {
        // return current tenant usage
    }
}
```

When `quotas_enabled` is on, the bundle aliases `QuotaEnforcerInterface` to `FeatureQuotaEnforcer` (replacing admin-bundle's unlimited noop for SaaS apps).

Commands
--------

[](#commands)

```
bin/console nubit:tenant:list
```

Per-tenant console jobs extend `Nubit\Platform\Symfony\Console\PerTenantCommand` — the bundle wires the connection switcher and a Doctrine-backed registry.

Resolution strategies
---------------------

[](#resolution-strategies)

StrategySource`user``TenantAwareUserInterface` on the authenticated user`jwt_claim``tenantId` / `tenantName` claims in the access JWT`header``X-Tenant-Id` (configurable)`subdomain`Tenant registry lookup by slug / domain

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

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 ~0 days

Total

4

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/990211?v=4)[Johan Guerreros](/maintainers/johangm90)[@johangm90](https://github.com/johangm90)

---

Top Contributors

[![johangm90](https://avatars.githubusercontent.com/u/990211?v=4)](https://github.com/johangm90 "johangm90 (2 commits)")

---

Tags

symfonybundlesaasmulti-tenantnubit

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nubitio-tenant-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/nubitio-tenant-bundle/health.svg)](https://phpackages.com/packages/nubitio-tenant-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.5M373](/packages/easycorp-easyadmin-bundle)[sulu/sulu

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

1.3k1.4M196](/packages/sulu-sulu)[open-dxp/opendxp

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

9317.2k55](/packages/open-dxp-opendxp)[chameleon-system/chameleon-base

The Chameleon System core.

1027.9k4](/packages/chameleon-system-chameleon-base)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1715.6k12](/packages/2lenet-crudit-bundle)

PHPackages © 2026

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