jeffersonsimaogoncalves / multitenancy
Adds domain based multitenancy to Laravel applications.
Requires
- php: ^7.4|^8.0
- spatie/laravel-permission: ^3.0|^4.0|^5.0
Requires (Dev)
- codedungeon/phpunit-result-printer: ^0.26.0
- orchestra/testbench: ^4.0
- phpunit/phpunit: ^8.0
README
This package is meant to be a quick and easy way to add multitenancy to your Laravel application. It simply creates models and relationships for Tenants and models. The package identifies incoming traffic by subdomain, and finds a corresponding tenant in the Tenant table. If none are found or the user is not associated with a particular subdomain, the user is met with a 403 error.
The admin
subdomain is reserved for the package. It is used to automatically remove all scopes from users with a Super Administrator
role.
To scope a resource to the currently accessed subdomain, you simply need to add a single trait to the model and add a foreign key relationship to the model's table. The package middleware will automatically apply the scopes for the relevant models.
Any resources saved while accessing a scoped subdomain will automatically be saved against the current tenant, based on subdomain.
Installation
You can install the package via composer:
composer require jeffersonsimaogoncalves/multitenancy
In Laravel 5.5 the service provider will automatically get registered. In older versions of the framework you should add the service provider in the config/app.php
file:
'providers' => [ // ... JeffersonSimaoGoncalves\Multitenancy\MultitenancyServiceProvider::class, ];
You can publish the config file with:
php artisan vendor:publish --provider="JeffersonSimaoGoncalves\Multitenancy\MultitenancyServiceProvider" --tag="config"
If you want the user to automatically be assigned to the Tenant it is created on you can enable this functionality by simply enabling the ignore_tenant_on_user_creation
setting.
You can automate most of the setup by running:
php artisan multitenancy:install
It will:
publish
andmigrate
required migrations- add a
Super Administrator
role andaccess admin
permission - add an
admin
Tenant model
Usage
First, add the JeffersonSimaoGoncalves\Multitenancy\Traits\HasTenants
and Spatie\Permission\Traits\HasRoles
traits to your User model(s):
use Spatie\Permission\Traits\HasRoles; use JeffersonSimaoGoncalves\Multitenancy\Traits\HasTenants; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasTenants, HasRoles; // ... }
The package relies on Eloquent, so you may access the User's tenants with User::tenants()->get()
.
Inversely, you may access the Tenant's users with Tenant::users()->get()
.
Tenants require a name to identify the tenant and and a subdomain that is associated with that user. Example:
tenant1.example.com
tenant2.example.com
These values could be added to the database like so:
Tenant::create([ 'name' => 'An Identifying Name', 'domain' => 'tenant1' ]); Tenant::create([ 'name' => 'A Second Customer', 'domain' => 'tenant2' ]);
You can then attach user models to the Tenant:
$user = User::first(); Tenant::first()->users()->save($user);
Middleware
Authenticated
This package comes with TenantMiddleware
middleware which extends Laravel's Illuminate\Auth\Middleware\Authenticate
. You can add it inside your app/Http/Kernel.php
file.
protected $routeMiddleware = [ // ... 'tenant.auth' => \JeffersonSimaoGoncalves\Multitenancy\Middleware\TenantMiddleware::class, ];
Then you can bring multitenancy to your routes using middleware rules:
Route::group(['middleware' => ['tenant.auth']], function () { // ... });
Guest Tenant
This package comes with GuestTenantMiddleware
middleware which applies the tenant scope to all models and can be used for allowing guest users to access Tenant related pages. You can add it inside your app/Http/Kernel.php
file.
protected $routeMiddleware = [ // ... 'tenant.guest' => \JeffersonSimaoGoncalves\Multitenancy\Middleware\GuestTenantMiddleware::class, ];
Then you can bring multitenancy to your routes using middleware rules:
Route::group(['middleware' => ['tenant.guest']], function () { // ... });
Tenant Assignment for Models
Models can automatically inherit scoping of the current tenant by adding a trait and migration to a model. This would allow users to access tenant1.example.com
and return the data from tenant1
only.
For example, say you wanted Tenants to manage their own Product
. In your Product
model, add the BelongsToTenant
trait. Then run the provided console command to add the necessary relationship column to your existing products
table.
use Illuminate\Database\Eloquent\Model; use JeffersonSimaoGoncalves\Multitenancy\Traits\BelongsToTenant; class Product extends Model { use BelongsToTenant; // ... }
Hint If the user is assigned
Super Administrator
access, they will be able to access theadmin
subdomain and the tenant scope will not register. This allows you to manage the data across all instances without needing individual access to each Tenant's account.
Get Current Tenant
You can get the current tenant model:
app('multitenancy')->currentTenant();
Providing Access to Admin Domain
In order to access the admin.example.com
subdomain, a user will need the access admin
permission. This package relies on Spatie's Laravel Permission package and is automatically included as a dependency when installing this package. We also provide a Super Administrator
role on migration that has the relevant permission already associated with it. Assign the Super Administrator
role to an admin user to provide the access they need. See the Laravel Permission documentation for more on adding users to the appropriate role and permission.
A subdomain for the admin portal will be created automatically during installation, but you can manually add it like this:
Tenant::create([ 'name' => 'Admin Portal', 'domain' => 'admin' ]);
Console Commands
Generate a migration to add tenancy to an existing model's table:
php artisan multitenancy:migration products
Assign a user Super Administration
rights and the admin
Tenant:
php artisan multitenancy:super-admin admin@example.com
Managing with Nova
There is a separate Nova Package available that allows you to manage the resources utilized in this package in Nova.
Reporting Issues
If you have a problem with this plugin or any bug, please open an issue on GitHub.
Credits
This work is based on the code by RomegaDigital.