Laravel. Be careful when using solo dynamic segments on Routes

First and foremost I’d like to illustrate what I call dynamic segments:

Dynamic Segment

Route’s dynamic segment receive information provided by users and they are tipically used to retrive stored data. In the image above both id and slug are used to query the database.

Working with routes and dynamic segments is something trivial and unlikely to give you any problem but there’s one situation which might make you run into some trouble.

Let’s take a look at the code below:

A typical Laravel's route set...

This is nothing more than a bunch of grouped routes. The $config array contains - among other things - the prefix for all the group’s routes.

The URL for the route configured on line 11 will be something like http://domain.com/feature. On line 12 there’s another route which URL will be http://domain.com/feature/< anything here >

Got the issue?

This < anything here > could be an integer (an ID for instance), could be a slug as declared in the route (my-wonderful-post-dat-will-change-your-life-foreva) OR it could be simply novo (new, in english…).

Let me draw it for you:

. http://domain.com/feature/187
. http://domain.com/feature/my-wonderful-post-dat-will-change-your-life-foreva
. http://domain.com/feature/new

Well, according to the script above route /new will never be reached, because “novo” might as well be a slug and then the script execution will stop on line 12, never getting to line 13, which is the original intent.

The easiest solution is to move the code in the line 12 to the end of route’s set. So, when all the more specific routes are checked and retuned false, then the request will certainly reach slug’s route.

The solution

Laravel 5.1 - easily enable CORS

CORS stands for Cross-Origin Resource Sharing an is a specification that allow modern browsers to request (and receive) data from a domain other than the one serving the page that made the request.

If this is the first time you’re hearing about this, please allow me to introduce you to these two great resources:

-http://www.html5rocks.com/en/tutorials/cors/
-http://enable-cors.org

So you’re building your API using Laravel and when when you try to make a XHR request you see the following message in your browser’s console:

This means your server is not sending back to the client the headers that allow CORS:

1.Access-Control-Allow-Origin
2.Access-Control-Allow-Methods

So how to implement this in Laravel? Super easy! Middlewares come to the rescue.

Using your Terminal, navigate to your project’s root directory and issue the following artisan command:

1
php artisan make:middleware Cors

Now, using your editor of choice, change the newly created /app/Http/Middleware/Cors.php so it look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace App\Http\Middleware;

use Closure;

class Cors {
public function handle($request, Closure $next)
{

return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}
}

Next update /app/Http/Kernel.php adding the following instruction which will make Laravel aware of your custom middleware:

1
2
3
4
5
6
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'cors' => \App\Http\Middleware\Cors::class, // <<< add this line
];

To wrap things up, just use your middleware as you’re used to:

1
2
3
4
Route::get('breweries', ['middleware' => 'cors', function()
{

return \Response::json(\App\Brewery::with('beers', 'geocode')->paginate(10), 200);
}]);

And that would be all. Of course there are several other options to consider when enabling CORS but the way to return them to the browser is the same, as shown right above.

Hope that helps!