Monday 15 May 2017 at 13:09

Domain Routing in Laravel

By Eric Antoine Scuccimarra

For quite a while I have been struggling to get domain routing working in Laravel. Subdomain routing comes out of the box, and what I read said that adding domain routing should be fairly easy.

The first thing to do is get the full domain passed into the router. By default Laravel only takes what comes before the first ".", so to get the full domain passed in you need to add this to your Providers/RouteServiceProvider.php file:

Route::pattern('domain', '[a-z0-9.\-]+');
 parent::boot();

Now you can access the full domain in the routes file, and you can do so by adding a route group:

Route::group(['domain' => '{domain}'], function ($domain) {

I tried to get the routes to take in the domain as a parameter and create themselves dynamically, but that did not work. So I ended up creating the route group. My issue was that some domains just use the normal route, and others were to have their own custom routes. I spent a while trying to get that working before just adding the route group. Inside the route group I check the database to see if this domain uses the normal routes or gets a special route. 

The next issue was how to pass the variables from the routes to the controller, when they do not come from the URL. The special routes can be accessed via URL: http://www.maindomain.com/site/1. I wanted to be able to map via http://www.customdomain.com to that URL, but to do so I needed to pass the parameters from the URL into the controller when the parameters do not exist in the URL. That took some more figuring out, but it turns out you can do it like this:

$app = app();
$controller = $app->make('App\Http\Controllers\WhateverController');
return $controller->callAction('show', ['request' => $request, 'id' => $id]);

The controller expects a Request object, and to get that passed in you need to add it to the route explicity:

Route::get('/', function ($domain, \Illuminate\Http\Request $request) {

With that addition I am able to map the custom domain to a specific controller and pass in variables which are determined in the routes file.

The final code looks like this:

Route::group(['domain' => '{domain}'], function ($domain) {
    Route::get('/', function ($domain, \Illuminate\Http\Request $request) {
        $site = \App\Website::where('host', $domain)->first();
        if($site){
            $app = app();
            $controller = $app->make('App\Http\Controllers\DomainController');
            return $controller->callAction('show', ['request' => $request, 'id' => $site->store_id]);
        } else {
            $app = app();
            $controller = $app->make('App\Http\Controllers\HomeController');
            return $controller->callAction('index', []);
        }
    });
});

So for route "/" it checks to see if the domain exists in a table in the database, if so calls DomainController with a parameter from the DB and the request. If not it calls HomeController.

After a long time spent trying to figure this out it turns out to be a lot simpler than I thought it would be. However now I need to add specific routes to some domains but not others. I don't expect that will be too different than the method I am currently using.

Labels: coding, laravel


Comments

Login or Register to leave a comment..


Archives