Route Patterns in Laravel 4

When using the excellent Laravel 4, writing DRY and SOLID code is something you’re well aware of. Unfortunately, it’s common for the routes file to get messy and repetitive as an application grows – enter the route pattern method. Even worse (in my opinion) is performing basic and repetitive validation of parameters in controllers.

Consider a routes file that responds to 4 simple URIs:

// routes.php
Route::get('questions/{slug}', 'QuestionController@show');
Route::get('people/{slug}', 'TeamController@show');
Route::get('subscriptions/{uuid}', 'SubscriptionController@show');
Route::get('directory/{id}', 'DirectoryController@show');

This is fine and will of course work, but is far from ideal. For example, the application would currently respond to undesirable requests like “/questions/**7_kld=723++n][u393—asd-asda”. Ideally, the application will only respond to certain types of route parameters E.g. integers, a slug consisting of lowercase letters and numbers, separated by a dash etc.

Enter route constraints, or the ability to validate the route parameter based on a regular expression:

// routes.php
Route::get('questions/{slug}', 'QuestionController@show')->where('slug', '[a-z0-9-]+');
Route::get('people/{slug}', 'TeamController@show')->where('slug', '[a-z0-9-]+');
Route::get('subscriptions/{uuid}', 'SubscriptionController@show')->where('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}+');
Route::get('directory/{id}', 'DirectoryController@show')->where('id', '\d+');

If a request for an invalid route is made, the application will throw an catchable exception (Symfony\Component\HttpKernel\Exception\NotFoundHttpException) and not hit the controller at all.

The application could even respond to an invalid page by displaying a message (or loading a view) and setting a 404 header:

// app/start/global.php
App::missing(function($exception) {
    return Response::make("Page not found :(", 404);
});

However, things remain rather messy for routes with multiple parameters:

Route::get('directory/{id}/process/{uuid}', 'DirectoryController@process')->where(['id' => '\d+', 'uuid' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}']);

Far from ideal, ouch.

Route Patterns

The routes.php file is getting a little repetitive and will only continue to do so as the application grows. For instance, what happens if logic is changed to match the “slug” parameter and the regular expression changes? Currently, a change to all mentions of this particular regular expression would need updating. This is exactly the type of code that should be avoided. Alas, Laravel has an answer – “Route Patterns“. This is mentioned in the official Laravel documentation, but in my opinion is not emphasised enough, as it’s a great feature. A simple change to the routes file is needed:

// routes.php
Route::pattern('id', '\d+');
Route::pattern('slug', '[a-z0-9-]+');
Route::pattern('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');

Route::get('questions/{slug}', 'QuestionController@show');
Route::get('people/{slug}', 'TeamController@show');
Route::get('subscriptions/{uuid}', 'SubscriptionController@show');
Route::get('directory/{id}', 'DirectoryController@show');

Benefits of Route Patterns

The route parameters have now been defined just once and in a single place using a new method, Route::pattern(). I look upon this as a kind of index or list of all the application route parameters, in one place. If a change is required we’d only need to make the update in a single place, much more convenient.

An added benefit can be seen when writing a route that requires multiple parameters:

Route::get('directory/{id}/process/{uuid}', 'DirectoryController@process');

… which is a lot neater than writing:

Route::get('directory/{id}/process/{uuid}', 'DirectoryController@process')->where(['id' => '\d+', 'uuid' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}']);

Enjoy, that’s the route pattern method in Laravel 4! 🙂

Published by

Rob Allport

Web Developer based in Stoke-on-Trent Staffordshire Google+ - Twitter

3 thoughts on “Route Patterns in Laravel 4”

  1. Hey, i tried this and it works… i will wait for more cool stuff. I will keep looking your blog. Please do posts more frequently.. I have read about 5 , 6 more posts about it, but your post was a bit better than those. Thanks for such a nice tutorial.

  2. That’s a good trick in all honesty. Why don’t the Laravel 4 people make more of a deal about this geature – it’s great! In their help site, I only see a very small mention of the route pattern function.

  3. Just tried this out and love it. Am going to rework my whole routes file that has admittedly become huge. Wish I had known about Laravels’ route patterns about a month ago!!!!!

Leave a Reply

Your email address will not be published. Required fields are marked *