Articles

Introduction to Tenancy for Laravel: What is it and Why Use it?

Posted by I. B. Gd Pramana A. Putra, 01 Mar 23, last updated 03 Mar 23

Multi Tenancy in Laravel

Laravel is a popular PHP web application framework that is widely used to build scalable and maintainable web applications. However, when it comes to building multi-tenant applications, Laravel can become a bit challenging. This is where Laravel Tenancy comes into play. In this article, we will introduce you to Tenancy for Laravel, what it is, and why you should use it.

What is Tenancy for Laravel?

Tenancy for Laravel is a package that allows you to create multi-tenant Laravel applications. With Tenancy, you can create a single Laravel application that can serve multiple tenants, each with its own database schema, data, and configuration. Tenancy achieves this by intercepting the incoming HTTP requests and dynamically switching the database connection and other configurations based on the tenant.

As an example, You have a multi-tenancy LMS application at aptreelms.com. When you or your user visits pram.aptreelms.com, you are actually using Aptree LMS owned by Pram, which that website has its own database and configuration, same scenario is applied to fachtur.aptreelms.com. Both websites use the same single codebase, therefore it's called multi-tenancy.

Why Use Tenancy for Laravel?

Simplified Development

With Tenancy, you can create a single codebase for your multi-tenant Laravel application. This means that you can reuse the same code for all tenants, and only the configurations and data will be different. This makes the development process simpler and more efficient.

Reduced Costs

Creating separate Laravel applications for each tenant can be costly and time-consuming. With Tenancy, you can reduce the costs and time spent on development by creating a single codebase and reusing the same code for all tenants.

Easy Management

Tenancy allows you to manage all your tenants from a single dashboard. You can easily create, update, and delete tenants, and manage their configurations and data.

Increased Efficiency

Multi-tenancy can increase efficiency by reducing development and maintenance efforts, and by providing a single application instance for multiple tenants. This reduces duplication of effort, leading to faster development and reduced time-to-market.

Example Usage

To use Tenancy for Laravel, you first need to install it using Composer. You can do this by running the following command in your terminal:

composer require tenancy/tenancy

Then, run the tenancy:install command:

php artisan tenancy:install

This will create a few files: migrations, config file, route file and a service provider.

Let's run the migrations:

php artisan migrate

Register the service provider in config/app.php. Make sure it's on the same position as in the code snippet below:

/*
 * Application Service Providers...
 */
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\TenancyServiceProvider::class, // <-- here

Create a Laravel Model for Tenant

<?php

namespace App\Models;

use Stancl\Tenancy\Database\Models\Tenant as BaseTenant;
use Stancl\Tenancy\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;

class Tenant extends BaseTenant implements TenantWithDatabase
{
    use HasDatabase, HasDomains;
}

Separate the central web routes and tenant routes by making a small change to the app/Providers/RouteServiceProvider.php file. Specifically, we'll make sure that central routes are registered on central domains only.

protected function mapWebRoutes()
{
    foreach ($this->centralDomains() as $domain) {
        Route::middleware('web')
            ->domain($domain)
            ->namespace($this->namespace)
            ->group(base_path('routes/web.php'));
    }
}

protected function mapApiRoutes()
{
    foreach ($this->centralDomains() as $domain) {
        Route::prefix('api')
            ->domain($domain)
            ->middleware('api')
            ->namespace($this->namespace)
            ->group(base_path('routes/api.php'));
    }
}

protected function centralDomains(): array
{
    return config('tenancy.central_domains');
}

Call these methods manually from your RouteServiceProvider's boot() method, instead of the $this->routes() calls.

public function boot()
{
    $this->configureRateLimiting();

    $this->routes(function () {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
    });
}

Specify the central domains. A central domain is a domain that serves your "central app" content, e.g. the landing page where tenants sign up. Open the config/tenancy.php file and add them in:

A central domain is a domain that serves your "central app" content, e.g. the landing page where tenants sign up. Open the config/tenancy.php file and add them in:

'central_domains' => [
    'saas.test', // Add the ones that you use. I use this one with Laravel Valet.
],

Now in your tenant.php route file, it should look like this:

Route::middleware([
    'web',
    InitializeTenancyByDomain::class,
    PreventAccessFromCentralDomains::class,
])->group(function () {
    Route::get('/', function () {
        return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
    });
});

These routes will only be accessible on tenant (non-central) domains — the PreventAccessFromCentralDomains middleware enforces that.

Now you can test if the tenant site is accessible or not by visiting your tenant site, inside your tenant.php file add the following codes example:

Route::get('/', function () {
    dd(\App\Models\User::all());
    return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
});

Conclusion

Overall, multi-tenancy can provide significant benefits over single-tenancy, especially for software applications that need to serve multiple customers with varying needs and requirements. However, it's important to carefully evaluate the requirements of your application and the needs of your customers before deciding on a multi-tenancy approach.

Although multi-tenancy can provide mentioned benefits, this approach can also significantly increase the DevOps complexity.

For more reading about Tenancy for Laravel: https://tenancyforlaravel.com/

References

Answer & Responses
    No comments yet

Wanna write a response?

You have to login before write a comment to this post.