PHPackages                             sinclairt/multi-tenancy - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. sinclairt/multi-tenancy

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

sinclairt/multi-tenancy
=======================

Multi tenancy solution inside a single app and single database

1.0.6(9y ago)09MITPHP

Since Jul 21Pushed 9y agoCompare

[ Source](https://github.com/sinclairt/multi-tenancy)[ Packagist](https://packagist.org/packages/sinclairt/multi-tenancy)[ RSS](/packages/sinclairt-multi-tenancy/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (4)Versions (10)Used By (0)

Multi Tenancy
=============

[](#multi-tenancy)

### Installation

[](#installation)

`composer require sinclairt/multi-tenancy`

Register the service provider in the config/app.php array: `\Sinclair\MultiTenancy\Providers\MultiTenancySericeProvider::class`

##### Optional

[](#optional)

Publish the config: `php artisan vendor:publish`

##### Config

[](#config)

**ignore-roles** *default(\[ 'super-admin' \])*
if you don't want your app to apply the multi-tenancy constraints add the roles here, I've assumed super-admin out of the box, but feel free to change this or leave as an empty array if you're not using roles

**public-space-roles** *default(\['super-admin'\])*
if you would like to protect your public domain with auth routes, you can set which roles should be allowed access to this area

**relationship name** *default('tenant')*
this is the name of the relationship method on your models, the plural is assumed for many-to-many

**relationship table** *default('tenants')*
name of the tenant table

**relationship class** *default(\\App\\Models\\Tenant::class)*
class name of the tenant model

**relationship polymorph-term** *default('tenantable')*
the polymorphic term used in you models relationships

**relationship foreign key** *default('tenant\_id')*
the foreign key used on your models tables

**relationship slug column name** *default('slug')*
the column where the slug is stored on the tenant table

**should apply callback** *default(null)*
if you want to use custom logic to decide whether to apply the scopes set you callback here the user object and ignored roles array are passed into this

**should apply default** *default(true)*
if true will automatically apply the scopes to the models, this is only used if the callback is null and the ignore roles are empty

**role class** *default(\\App\\Models\\Role::class)*
The name of your role class - leave as an empty string if you're not using roles

### Set Up

[](#set-up)

Inside `config/auth.php` you will need to set up a new guard and a new provider like so:

```
// guard
'tenant' => [
            'driver' => 'session',
            'provider' => 'tenants'
        ]

// provider
'tenants' => [
            'driver' => 'tenant',
            'model'  => App\Models\User::class,
        ],

```

You may also like to set the default guard to tenant or set an if statement up, otherwise you will need to specify the guard when interacting with the `Auth` object:

```
'guard'     => !is_null(constant('TENANT_SLUG')) ? 'tenant' : 'web',

```

The multi-tenancy package works by using global scopes to restrict queries based on a constant `TENANT_SLUG`. This package assumes you are using a sub-domain to control which tenant is required by your user; there is a helper function to place inside bootstrap/app.php `bootstrapMultiTenancy()`, but, of course, you are free to set the constant however you wish, but in order for this package to work it must be set.

### Usage

[](#usage)

To avoid having a foreign key on every single database table, the multi-tenancy package uses a models relationships to constrain queries. There a three ways a model can be connected to a tenant:

- Directly - the model belongs to the tenant
- Through - the model belongs to the tenant through another model or chain of models
- Morph - the model belongs to the tenant via a many-to-many relationship (polymorphic included)

There are three scopes that can be applied based on the criteria above, and there are traits to ease the implementation for two of them: the ` BelongsToTenant` and `MorphToTenant` scopes have respective traits, just use them in your models and that's it.

The other scope `BelongsToTenantThrough` requires a little more set up, but only a little, all you need to do is set the relationship(s) to go through to get to the tenant when applying the scope in the models boot method, for example:

```
    public static function boot()
    {
        parent::boot();

        static::addGlobalScope(new BelongsToTenantThrough('user'));
    }

```

The vehicle model in the example above belongs to the Tenant in one way or another and so we will go through this relationship to get to the tenant.

You can also use dot notation to chain relationships i.e. `driver.user`, this applies when there are series of relationships to go through to get to the tenant.

One final scenario is if your model is a polymorphic many-to-many and could potentially belong to the tenant through various channels, easy, pass in an array of all the potential links to the tenant, the multi-tenancy package only needs to find one:

`static::addGlobalScope(new BelongsToTenantThrough([ 'users', 'drivers.user', 'locations' ]));`

In this example we have a Phone model which stores numbers against various models: users, drivers, and locations, so we need to check whether it belongs to our given tenant through any of those connections.

### User Model

[](#user-model)

Because the multi-tenancy package allows you to have a single database, it means a user can belong to more than one tenant if you want them to, useful for admin roles (although I recommend using the ignore-roles config value). If you use the sub-domain solution for multi-tenancy this will force the user to login to new tenant areas but it means they can have the same credentials, roles, and permissions across tenants.

Your User model needs to use the `IsMultiTenantUser` trait if you are using roles, it provides a piece of logic for the scopes, but it also uses the `MorphToTenant` trait and sets the roles relationship for you. If you're not using roles, be sure to use the `MorphToTenant` trait in your User model.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity69

Established project with proven stability

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

Recently: every ~44 days

Total

9

Last Release

3328d ago

Major Versions

0.0.2 → 1.0.02016-09-12

### Community

Maintainers

![](https://www.gravatar.com/avatar/a0dc010eef4e76d1eb705b4f2257422302ada2164add753976f7998d9203b19a?d=identicon)[sinclairt](/maintainers/sinclairt)

---

Top Contributors

[![sinclairt](https://avatars.githubusercontent.com/u/16877448?v=4)](https://github.com/sinclairt "sinclairt (3 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sinclairt-multi-tenancy/health.svg)

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

###  Alternatives

[dive-be/laravel-geo

Translate IP addresses into geo locations

3710.5k](/packages/dive-be-laravel-geo)[ghost/dcat-config

配置管理

112.2k](/packages/ghost-dcat-config)

PHPackages © 2026

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