We're live-coding on Twitch! Join us!
How to build a multi tenant site with Laravel

How to build a multi tenant site with Laravel

Laravel is a wonderful framework, however the default settings make it difficult to use for more than one domain at the same time.

A multi tenant site is one that uses the same codebase to serve data to multiple clients. A very popular example of this is slack.

A multi tenant site will usually require that each tenant accesses the site from a unique url, and this causes problems because laravel by default, does not permit this behavior.

The APP_URL set in the .env file is used to generate the routes, the asset urls, and many other things and by default, there is no way to set multiple urls.

To allow us to use multiple domains, we will have do a some customisations.

Understanding the solution

Usually, multi-tenant applications require certain differences for each tenant, one common change is the url, there may also be a different set of database credentials, or API keys.

Laravel only allows one .env file so what we are trying to do, is to change the .env file BEFORE it is loaded as configurations by laravel.

We will want to define the environment values that are different for each tenant, but also allow the common environment variables to be defined once.

Step 1: Creating the files.

We will add a folder to the root of our project called env and we will put the different env files here.

Next, name each file the domain name you'd use to access it. e.g. example.com and example2.com

Inside the files, define the env values you want to overide when you visit the application through that domain.

Step 2: Loading the variables

Laravel makes use of the vlucas/phpdotenv package to load environmental variables. From the readme of the package we can see this.

Immutability

By default, Dotenv will NOT overwrite existing environment variables that are already set in the environment.

If you want Dotenv to overwrite existing environment variables, use overload instead of load: 

So what we have to do, is to load our environment variables first, and then when Laravel loads the default .env file, it will not overwrite the variables already set.

We will load the domain file after the autoload, so that we have access to the vlucas/phpdotenv package but before Laravel is fully loaded.

So in public/index.php after the line

require __DIR__.'/../bootstrap/autoload.php';

add the following line

require __DIR__.'/../bootstrap/env.php';

Now go to the bootstrap folder and create a file named env.php and add this.

   <?php

    $host = $_SERVER['HTTP_HOST'];

    $env_dir = __DIR__.'/../env/';

    if (file_exists($env_dir.$host));
    {
        $dotenv = new \Dotenv\Dotenv($env_dir, $host);
        $dotenv->load();
    }

That's it!

Now any variable you want to overwrite such as the APP_URL you can simply set in the domain configuration file.

Like this article? Follow @stephenafamo on Twitter