Make your Laravel application multi-tenant without changing a line of code

Samuel Štancl • October 6, 2019

A package of mine, stancl/tenancy, lets you add multi-tenancy to Laravel applications without having to change how you write your app.

It automatically switches the database connection, cache, filesystem, Redis and queue in the background, letting you write code that doesn't need to be aware of any specifics related to multi-tenancy.

You can read more about the package here: tenancy.samuelstancl.me.

Installation

To install the package, first you need to require it via composer:

composer require stancl/tenancy

Then, you can use the install command to publish all assets and make the necessary changes to your http kernel.

php artisan tenancy:install

If you're not running this in a fresh Laravel application, it's wise to see what the install command does. It could cause issues if your application structure is too custom. Installing the package manually shouldn't take more than a minute.

Routes

For this package, routes are what distinguishes the tenant part of the application from the central part. Rather than applying model traits and similar things, just decide what routes belong to the tenant part of the app.

Routes for your tenant part of the application must be located in routes/tenant.php.

The routes/web.php file should be used for "central" routes — landing page, sign up page, etc.

Note that routes in these two files can't be conflicting, so it may be useful to prefix all tenant routes with app/, for example.

Domains

By default, when the application is visited, the package attempts to find a tenant who owns the domain in the request.

If the current domain doesn't belong to any tenant, an exception is thrown.

Add the domains for the central part of the application to the tenancy.exempt_domains config:

// config/tenancy.php
'exempt_domains' => [
    'yourapp.com',
],

Tenant migrations

Move the migrations that should interact with tenant databases to migrations/tenant.

Creating tenants

Finally, creating tenants. The last step to have a working multi-tenant app.

To create a tenant, you may use the following method:

use Stancl\Tenancy\Tenant;

Tenant::new()->withDomains([
    'client1.yourapp.com',
    'client1.com',
])->save();

To test your application locally, you may use domains under the .localhost top level domain. All of those domains are routed to 127.0.0.1.

Testing it out

Let's create two tenants: one on the foo.localhost domain and one on the bar.localhost domain.

You can run these methods in php artisan tinker for development.

use Stancl\Tenancy\Tenant;

$tenant1 = Tenant::new()->withDomains('foo.localhost')->save();
$tenant2 = Tenant::new()->withDomains('bar.localhost')->save();

Make sure your application is running on localhost and your web server accepts all hostnames (artisan serve does).

Now, you can visit your multi-tenant application on foo.localhost and bar.localhost, with both tenants having their own database, cache, queues, filesystem, and Redis.

It's likely you'll get a Table not found error when you visit the page — if it interacts with the database. To run tenant migrations, use the following artisan command:

php artisan tenants:migrate

Closing

And that's all there is to implementing multi-tenancy with stancl/tenancy.

Of course, in real world applications you need more things:

All of this, and much more, is covered in the package's documentation.

Thank you for reading this and I wish you success with your Software-as-a-Service.