Multiple websites from one Laravel instance

Multiple websites from one Laravel instance

Run multiple websites on different domains or subdomains from one Laravel project instance.

Run multiple websites on different domains or subdomains from one Laravel project instance.
Multiple websites from one Laravel instance

There may be a number of scenarios where it would be useful for one Laravel instance to serve several different websites: you may have a web app on one url and marketing or support websites on different urls but wish to only maintain one Laravel project. It may also reduce server resources required, enable you to share assets more easily between the sites, and only have one git repo to maintain.

If you need hosting for your Laravel projects, we like DigitalOcean, you can get $100 hosting credit to try it out if you sign up via this link.

Luckily, thanks to Laravel’s Route Groups functionality it’s a relatively easy process to run websites using multiple domains and subdomains from one single Laravel project.

Scenario:

Let’s say you have three key websites for your product, domain1.com, domain2.com and a support site on the subdomain support.domain1.com. We want the functionality for all three domains, and their models, views and controllers all to reside in one single Laravel instance.

Solution: 

To do this we need to make some changes to the routes/web.php file.

In a new Laravel install, the default route in web.php is: 

Route::get('/', function () {
    return view('welcome');
});

And a route that uses a controller would be e.g: Route::get('/blog', [BlogController::class, 'index']);

For Laravel to understand the particular domain for a route and direct it correctly, we need to use the Route::group() functionality, which for our three example domains would give us:

Route::group(['domain' => 'domain1.com'], function () {

    Route::get('/', function () {
        return view('domain1.welcome'); // domain1.com home page
    });

    Route::get('/blog', [BlogController::class, 'index']);
});

Route::group(['domain' => 'domain2.com'], function () {

    Route::get('/', function () {
        return view('domain2.welcome'); // domain2.com home page
    });
});

Route::group(['domain' => 'support.domain1.com'], function () {

    Route::get('/', function () {
        return view('support.welcome');
    });
});

The particular views returned in this example are referencing subfolders e.g. /resources/views/domain1/welcome.blade.php 

This is a basic example with the domains coded into the routes file. A more flexible approach that will be more effective for local and live environments is to store the domains in your environment file, then the production environment can point to your live domains and your local environment can use your local test domains. 

To do this, we create a sites.php within /config, and add the following (we have fallbacks using the live URLs):

'urls' => [
        'domain1' => env('DOMAIN1_URL','https://www.domain1.com'),
        'domain2' => env('DOMAIN2_URL','https://www.domain2.com'),
        'support' => env('SUPPORT_URL','https://support.domain1.com')
    ]

Then in your production .env file you can add:

DOMAIN1_URL=https://www.domain1.com
DOMAIN2_URL=https://www.domain2.com 
SUPPORT_URL=https://support.domain1.com

And your local environment (depending on your local setup but if using Valet):

DOMAIN1_URL=http://domain1.test 
DOMAIN2_URL=http://domain2.test 
SUPPORT_URL=http://support.domain1.test

Then in our routes file we can use:

Route::group(['domain' => Config::get('sites.urls.domain1')], function () {
// Routes go here
});

Now we need to configure our local and production environments to work with these domains.

For the local environment we’re just going to go through configuring using Valet as it’s the most popular default solution. Similar configurations can be set up for Docker and Homestead.

All we need to do for Valet is navigate to our project folder in a terminal and enter valet link domain1 and valet link domain2 (subdomains should automatically link with Valet).

Now you should be able to navigate to http://domain1.test and see the domain1 content, and http://domain2.test for the domain2 content.

For your live environment, (we like DigitalOcean for hosting, you can get $100 hosting credit to try it out if you sign up via this link.) you will need to add and configure the domains on your hosting platform in the usual way for a single site/project, but each domain will need its public folder to point to/use the same /public folder from your multisite Laravel project. 

A small bonus tip: If you need to get the current site URL you can use request()->getSchemeAndHttpHost() for the complete URL with 'https://' or request()->getHttpHost() for the URL without the scheme information.

We hope this has been helpful in getting your multisite Laravel project up and running, as always there’s plenty more information in the Laravel docs.

Related posts:
Multiple websites from one Laravel instance
Adding Google ReCaptcha to forms in Laravel
Laravel Wink - A Beginner's guide