Les billets libellés: laravel. Afficher tous les billets.

Domain Routing in Laravel

lundi 15 mai 2017

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.

Libellés: coding, laravel
Aucun commentaire

Domain Routing in Laravel

lundi 15 mai 2017

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.

Libellés: coding, laravel
Aucun commentaire

Queries by Key in Laravel

dimanche 07 mai 2017

One of my greatest frustrations with Eloquent collections has been that I needed to loop through the collection and either create a new collection or array if I wanted to have the results in a format where I could access them by a value in the query results. That is to say if I want to be able to access the results by say primary key, I would need to loop through the Collection returned by the query and create a new object with the key as whatever I wanted it to be.

I just learned that there is a much easier way to do this: 

    Model::all()->keyBy('whatever');

This will return the collection with "whatever" as the key, which makes life so much easier and code so much cleaner.

Libellés: coding, laravel
Aucun commentaire

I tried a bunch of different things to try to address the issues I was having with using Socialite in a site that has multiple domains. The problem ended up being the session domain. I was able to generate callback URLs for each domain easily, but I couldn't get around the session domain issue.

Rather than spend more time on this I ended up using a little workaround. From my login page if you click on the login with whatever provider button it directs you to one domain, the one that the session domain is set to, and from there the Socialite logins work fine.

It's not ideal, but the worst that will happen is that someone ends up on a different domain than they started on. 

Libellés: coding, laravel
Aucun commentaire

I've been struggling with an error with Laravel Socialite for months now. At times the socialite login worked perfectly, but at other times and with certain providers I got an error:

InvalidStateException in AbstractProvider.php line 200

This was not critical functionality so I just kept pushing it off, but finally we have found the solution. It is related to the domain in config/session.php. This value defaults to NULL, and it apparently needs to be set to the domain the site is running on. This site in question runs on many domains, so setting the value to a single domain fixes one domain but leaves all the rest broken.

So for me the issue is not solved, but at least I am not seeing that error anymore.

Libellés: coding, laravel
Aucun commentaire