Please note that this chapter was written for VERSION 3 of the Laravel PHP Framework.
In this chapter we will be using Routes with Closures instead of Controllers with Actions. If you have not yet read the previous chapter on the topic of using controllers then I would suggest starting there since we will be building on what we have already learned in this chapter.
Routes allow us to map our framework URLs to closures, which is a very clean way of containing our logic without all of the 'class fluff'. Closures are anonymous functions (function() {}
), they can be assigned to and treated like any other variable. For more information on Closures, check out the PHP API article.
Closures
Lets have a look at a route that routes to a closure.
<?php
// application/routes.php
Route::get('/', function()
{
return View::make('home.index');
});
In this example we are responding to requests to the root of the web application that use the HTTP verb GET
with a closure that simply returns a view object. The output is the default welcome page.
Please note that you only need the root slash for the root page, all other routes omit it, for example..
<?php
// application/routes.php
Route::get('account/profile', function()
{
return View::make('account.profile');
});
Routes are RESTful by nature, but you can use Route::any()
to respond to any HTTP verb. Here are your options:
<?php
// application/routes.php
Route::get();
Route::post();
Route::put();
Route::delete();
Route::any();
To pass parameters to your closures simply add the usual view place-holders to the URI, and define parameters in your closure. They will be matched in the order from left to right, for example..
<?php
// application/routes.php
Route::get('user/(:any)/task/(:num)', function($username, $task_number)
{
// $username will be replaced by the value of (:any)
// $task_number will be replaced by the integer in place of (:num)
$data = array(
'username' => $username,
'task' => $task_number
);
return View::make('tasks.for_user', $data);
});
Available placeholders are:
| Placeholder | Explanation |
|--------------|-----------------------------------|
| (:any) | Match any alpha-numeric string |
| (:num) | Match any whole number. |
| (:any?) | Optional parameter. |
Redirects and Named Routes
It would be kinda silly to look at named routes before seeing a method that uses them wouldn't it? Let's have a look at the Redirect class, it can be used to Redirect to another route. It can be used in a similar fashion to returning a view.
<?php
// application/routes.php
Route::get('/', function()
{
return Redirect::to('account/profile');
});
Lovely! Couldn't be simpler, wait no, it could, and is! Lets take a look at a named route :
<?php
Route::get('account/profile', array('as' => 'profile', 'do' => function()
{
return View::make('account/profile');
}));
Instead of passing a Closure as the second parameter, we now pass an array with the key 'do' pointing to the closure. This allows us to add all kind of extra information to the route.
The 'as' key, assigns a nickname to our route, this is what named routing is all about. Let's see how it can be used to improve the Redirect::
from before.
<?php
Route::get('/', function()
{
return Redirect::to_route('profile');
});
There, now we have that nasty URI out of our code, very pretty. All of the classes or helpers which refer to routes have a similar method to route to a named route. This can really clean up your code, and makes it read like a book. Also, if you later decide to change the URI for a certain page, you will not have to go back and change all of your links and redirects!
Filters
Ok ok... I said I was going to be explaining Routes in this one, but I honestly can't think of a better place to cover Filters, and they are related, so here we go.
Filters are exactly as they sound, they are code or tests that can be performed 'before' or 'after' a route, and other key events within the framework. Laravel has four special route filters that are defined by default in application/routes.php
. Let's take a look at them.
<?php
Route::filter('before', function()
{
// Do stuff before every request to your application...
});
Route::filter('after', function($response)
{
// Do stuff after every request to your application...
});
Route::filter('csrf', function()
{
if (Request::forged()) return Response::error('500');
});
Route::filter('auth', function()
{
if (Auth::guest()) return Redirect::to('login');
});
The first two routes execute the encapsulated closure before and after every request (or route / action) to your application. What you do within the enclosure is entirely up to you. Start libraries, provide data to 'something', your own creativity is your only limitation. They are special filters in that they do not need to be assigned to individual routes.
The 'csrf' filter is used to prevent 'cross-site-request-forgery' and can be applied to routes which are the result of an AJAX call for extra security.
The 'auth' filter can be applied to any route to prevent access unless a user is currently 'logged in' using Laravel's authentication system.
To apply 'csrf' or 'auth' filters to your Routes, simply add a new array entry to the second parameter like so:
<?php
Route::get('/', array('as' => 'profile', 'before' => 'auth', 'do' => function()
{
return View::make('account/profile');
}));
The key for the array can be either 'before' to run the filter before your route, or 'after' to run it after. Multiple filters can be applied by separating their names with a | (pipe) for example auth|csrf
.
As of Laravel 3.1, if you would like to add a filter to a number of requests whose URIs match a specific pattern, use the following line :
<?php
Route::filter('pattern: admin/*', 'auth');
This will apply the 'auth' filter to all route URIs that start with admin/
.
Route Groups
You may want to apply a number of settings across a range of routes. You can do this easily using the route grouping option, take a look..
<?php
Route::group(array('before' => 'auth'), function()
{
Route::get('panel', function()
{
// do stuff
});
Route::get('dashboard', function()
{
// do stuff
});
});
Now both the panel and dashboard routes are protected by the 'auth' filter.
Although routing can be very simple, routes can also be as complex as you need them to be. Use route groups to avoid duplicating common rules across many routes and keep your code DRY. (Don't repeat yourself!)
The next chapter will cover the creation of links, so that we can move from one routes page to the next. Hopefully you will already know how to move from one book page to the next.
My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.
It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!