Laravel: my first framework. Chapter 3 – Routing

The following content is the third chapter of my new e-book titled “Laravel: my first framework“. This writing is copyright by Maksim Surguy. Unauthorized copy and distribution of this material is prohibited.

Chapter 3. Routing

This chapter covers

  • Basics of routing
  • Passing parameters to routes
  • Route filters
  • Grouped and named routes
  • Redirects

When you come to a coffee shop and ask a barista for a cup of coffee, you wouldn’t be too happy if he gave you a bottle of hot sauce or would just quietly stare at you instead not even acknowledging that you are there or that your order has been received. Like the process of ordering coffee at a coffee shop through a barista, every web application should have final and desired destinations in its flow. When visitors come to your website or web application, they expect to receive what they requested. If they go to their user profile page and they see an empty or wrong page instead, frustrated and disappointed they might not come back to your application again.

By now you already have the general idea of how a Laravel application is built and you might be aware of how Laravel directs the flow of the application by the means of routing. Laravel has great routing capabilities, it provides the developer with instruments to create and fine tune application’s responses to requests. In this chapter you will learn in detail about Laravel’s powerful routing mechanisms and how you can set up those final destinations – routes in your web application to make your users happy. You will also learn about sending very specific requests to your application by means of route parameters and how Laravel can understand and process them. Finally, you will learn about protecting routes with route filters, grouping routes and making routes respond with the expected results.

3.12 Introduction to Routing in Laravel

As users or API’s interact with your application they will visit different pages, different destinations of the application, which in web development talk, are called “routes”.

 What are routes?
Routes define the endpoints of a web application, the final destinations of an incoming request.

Imagine that you are trying to create a login page for your application. Without defined routes your application simply will not know what to do when it receives a request from a user. Where should a request go? How should the application respond to browser’s requests? The routes act as virtual roads and pathways that the user’s requests can travel through, and your application will need to know where the requests can and cannot go. If your application needs to show a login page it will need to have a route defined for it. Also most likely there will be some processing or validation of the data entered on the login page. That also requires specifying a route. In Figure 3.1 Let’s take a look at the result that we would like to achieve:

Figure 3.1 Simplified login page flow

Figure 3.1 Simplified login page flow

In Laravel, the routes for a web application reside in “app/routes.php” file and are evaluated in the order from the bottom to the top. This is the file that you will edit each time you want to add or delete a route to your application. Having a brand new installation of Laravel, open up the “routes.php” file inside “app” folder and you will see that it has a single basic route already set up for the application’s index page (listing 3.1):

Listing 3.1 Contents of routes.php file in a fresh Laravel installation

// Route that is executed when the user opens up the index page in the browser
Route::get('/', function()
{
  return View::make('hello');
});

Remember when you first installed Laravel and opened the index page of your application in the browser, you saw a simple page with Laravel logo and text that said: “You have arrived”? The route above is the route that your application followed to show that first “hello” page (figure 3.2).

Figure 3.2 Laravel’s response to the index route

Figure 3.2 Laravel’s response to the index route

3.12.1 Structure of a basic route

A basic route like the index route already present in a fresh Laravel installation consists of three parts, the method of the incoming request (get, post, put, patch or delete), the destination of the route and the function that will be executed when the route destination is reached. Let’s take a look at an overview of route’s structure in figure 3.3:

Figure 3.3 Structure of a basic route

Figure 3.3 Structure of a basic route

The destination of the request could be one of the following:

  • A single slash, which is the root of the application
  • A single word like “users”, “posts” ,”about” and etc.
  • Words separated with a slash like “user/profile”, “tags/search”, “pages/company/profile” and etc

In plain English, the route shown in the figure 3.1 could be translated as:

"When I go get the index page create the view "hello" and serve it to me."

The View::make displays a Blade template specified in its parameter. Don’t worry if this doesn’t seem familiar to you. I will talk about Blade templating in later chapters but for now you just need to know that View::make shows an HTML page.

If you want to replace the destination with something other than the root of the application, for example with “coffee”, simply place “coffee” in the destination string parameter instead of the forward slash (listing 3.2):

Listing 3.2 Laravel application responding to request for “coffee”

// The index route destination (‘/’) has been replaced with “coffee”
Route::get('coffee', function()
{    
  // The response from the route is still the same
  return View::make('hello');
});

Now if you go to this modified route in the browser you will still see the default Laravel welcome page but at a new destination – “coffee” (figure 3.4). Knowing this you can now easily define a route for your barista application and be able to process a simple request for “tea”, “latte” or even “beer”!

Figure 3.4 The default root route of the application has been replaced with “coffee”

Figure 3.4 The default root route of the application has been replaced with “coffee”

3.12.2 Types of route requests

Web applications can do a lot more than just displaying pages. The routes with the method “GET” are mainly used to request some HTML content from the user’s browser. But what if you wanted to submit a form instead of showing a page? You might know that there are other types of HTTP request methods that are more appropriate. Some of the most popular HTTP methods used in web applications today are:

  • GET
  • POST
  • DELETE
  • PUT
  • PATCH
  • TRACE
  • HEAD

Laravel supports all of these HTTP methods in its router. The first five (GET, POST, DELETE, PUT and PATCH) are more than enough for vast majority of web applications. Technically we can even get by with using just the first two methods (GET and POST) for retrieving and submitting data but when you deal with things like APIs or frontend MVC frameworks like Backbone.js or AngularJS, you will see why there is a need for the rest of the HTTP methods. Table 3.1 shows a summary of HTTP request methods that you might use in your Laravel applications and the purpose of each method along with a simplified example.

Table 3.1 Most popular HTTP request methods supported in Laravel

Method Purpose Examples
GET Retrieving data Showing HTML page or echoing JSON content
POST Sending data Submitting contents of a form
PUT Updating a resource Updating a blog post or a comment
PATCH Modifying parts of a resource Updating a paragraph of existing blog post or a detail about the user
DELETE Removing a resource Deleting a blog post, an image or a comment.

3.12.3 Routing example: login form

I imagine that your Laravel applications will not only display static content and HTML pages but will also provide a certain degree of interaction between the user and the web application. For example the user might be presented with a login form and submit his or her username and password to your application. The routing flow to show the login page to the user is shown in figure 3.5:

Figure 3.5 Routing flow that shows a login page

Figure 3.5 Routing flow that shows a login page

Applying the concepts that we have learned in sections 3.1.1 and 3.1.2 let’s build routing for such application flow. We know that this simple application will need to show a login form. When the form is submitted by the user, it will send the entered data to the application. For purpose of seeing the routing concept in action, upon submittal of the form we want to just display the submitted data back to the user. Please see figure 3.6 that shows the flow of the form submission:

Figure 3.6 Routing flow for login form submission

Figure 3.6 Routing flow for login form submission

3.12.3.1 Building routing structure for the login form example

Let’s build the routing endpoints of the login form:

  • A route that shows the login form
  • A route that receives the submitted form and displays data back to the user

Using the proper HTTP methods from the table 3.1 we will need to use “get” method to request the login page and “post” method to process the form submission. First, we will build a skeleton for these two routes that will hold the logic of serving the form and processing the form (listing 3.3):

Listing 3.3 Structure of routes that display and process a login form (“app/routes.php”)

// Route definition for showing the login page
Route::get('login', function()
{    
  // Display a placeholder text to the user
  return 'login form';
});

// Route definition for processing the login form
Route::post('login', function()
{    
  // Display a placeholder text to the user
  return 'processing the login form';
});

The code in listing 3.3 will show the text ‘login form’ when you go to the ‘login’ route of your application. If you were to execute a POST request to the same route, you would see the text that says “processing the login form”. This is almost functional but we would like to see an actual form, don’t we?

3.12.3.2 Showing HTML form and processing user input

The simplest way to show HTML from the routes of the application is to just return the HTML as a string of text from the route. While a more proper way of doing this would be to create a view template and use Laravel’s Blade engine to display a form, we will resort to just outputting HTML straight from the route for the sake of simplicity. Let’s look at the code of listing 3.4 that displays the login form to the user.

Listing 3.4 GET Route that displays the login HTML form

// The HTML of the login form is returned from the route
Route::get('login', function()
{
  return '<form action="login" method="post">				
    Username: <input type="text" name="username"><br>			
    Password: <input type="password" name="password">			
    <input type="submit" value="Submit">					
    </form>';								
});

When the user submits this form from the login page, a request of type “POST” will be made to the login route, let’s just display entered information back to the user (listing 3.5):

Listing 3.5 POST Route that processes the login form input

// Capture submitted data and display it back to the user
Route::post('login', function()
{
  return 'Username:'.$_POST["username"].',Password: '.$_POST["password"];
});

Try visiting the “login” route in your browser at “http://localhost:8000/login” and submitting a username and password, you should get back the data that you have entered just like we saw in figure 3.4. Please note, this code might not look pretty because we are not using the proper Laravel instruments to show the form (Blade templates) and to capture the form data (Laravel’s Input::get method). In later chapters you will learn how to build the same functionality in a much cleaner way.

Laravel is not limited to just responding to requests. There could be times when you will need to make your routing more dynamic or impose some limits on what the routes will respond to. The most prominent of Laravel’s instruments in its routing arsenal that will help you achieve a degree of protection and dynamism are route filters and route parameters. Route filters allow you to execute a specific function before or after a certain route is executed. This can be incredibly helpful when you are trying to limit certain routes to only logged in users or to users possessing a certain criteria. I will elaborate on the route filters a bit later in this chapter, but for now I would like to introduce you to one of the most often used instruments of Laravel’s routing – passing parameters to your routes.

3.13 Passing parameters to routes

Route parameters allow the routing of your application to become dynamic and adapt to the data that your application is working with. The data in your application most likely will not be all hard coded. Some of it will be stored in a database; some of it will be stored in sessions, some will be passed down from one part of the application to another. When your application becomes alive and filled with information, there will arise a need to access specific bits and pieces of that data.

Referring back to the coffee shop barista example from the introduction to this chapter, let’s say you ask a barista for a specific kind and size of coffee: “I would like a Grande Latte”. How can you make a web application understand specific details about the requested data (size – “Grande”, kind – “Latte”) and respond back to you differently depending on those details?

The answer is: you can do it by using route parameters. You need to somehow tell the application what type of resource you are requesting or provide details about the resource in some way. One way of doing that is to have a form on each page of your application and submit that form that contains all details about the data. That is a very bad, outdated practice and I do not recommend you do that! Instead of having everything in forms, we can utilize something that a server already understands and gets from you as soon as you access a web page – the requested URL. That’s right, the address bar in your browser can provide you web application with a lot of data. Let’s examine a sample URL structure of a request to a barista-like application that we would like to achieve (figure 3.7):

Figure 3.7 URL with route parameters

Figure 3.7 URL with route parameters

From a URL like that, “http://localhost:8000/coffee/latte/grande”, we can see what exact resource we would like to request from the barista application. We have provided the details about what type of resource we are requesting (coffee), the kind (latte), and the size (grande). Going to a URL like this without specifying the routing for it in the application will throw a “Not Found” exception because first we need to define the routes for this type of request.

In the previous section you have learned that you can have words separated by a slash in your destination URL for the routes. So one way to achieve routing for specific kind and size of coffee would be to declare a route for each possible kind and size of coffee, something like the code of listing 3.6:

Listing 3.6 Inefficient example of routing to specific kinds and sizes of coffee

// Route to coffee/latte/grande
Route::get('coffee/latte/grande', function()				
{     
  return 'Grande Latte';
});

// Route to coffee/latte/venti
Route::get('coffee/latte/venti', function()				
{     
  return 'Venti Latte';
});

... // 57 more routes (!)

// Route to coffee/espresso/grande
Route::get('coffee/espresso/grande', function()
{     
  return 'Grande Espresso';
});

This type of routing would quickly get out of hand and become nearly impossible to manage if you have 20 different kinds of coffee drinks and 3 different sizes for each kind. That would be 60 routes in total! Isn’t there a better way of doing this in Laravel? There sure is, and it is route parameters that you could use to make this routing better.

3.13.1 Using route parameters

It would be nice if you could just give that function inside of the route definition some variable along with some sort of template in the route destination that defines where that variable can occur and Laravel would automatically make that into a dynamic route that responds to different URLs but has the same behavior for all of those URLs. Guess what, this is exactly what Laravel can do. The code in listing 3.7 shows how to use the route parameter to display any kind of coffee drink:

Listing 3.7 Route with a parameter

// Passing a parameter to the route “coffee” to dynamically 
// specify a kind of coffee.
Route::get('coffee/{kind}', function($kind)
{
  // Displaying the variable back to the user
  return 'Requested kind of coffee drink: '.$kind;
});

Now if you go to any URL like coffee/espresso or coffee/latte or coffee/cappuccino (relative to application’s URL), your application will tell you which kind of coffee you have requested. No more statically declared routes that know only one thing. This is so powerful!

3.13.1.1 Passing more than one parameter

Even though we have achieved some degree of dynamics in our barista application, we have not accomplished our goal, we still cannot ask for a specific size of our coffee drink. We are not limited to passing just one parameter however, in the same way of passing a single parameter we can pass two, three or as many as we would like by defining them in the destination string template and passing them as the arguments to the function inside of the route, like in listing 3.8:

Listing 3.8 Route with multiple parameters

// Passing two parameters to a single route
Route::get('coffee/{kind}/{size}', function($kind, $size)
{
  // Displaying the variables back to the user
  return 'Kind of coffee drink: '.$kind.', size: '.$size;
});

Voila, now you can request a coffee/espresso/tall, or coffee/latte/grande or coffee/cappuccino/small or any other size or kind of coffee and your application will know what to do with it based on our route destination template.

3.13.2 Route constraints

In some cases you will want to have only certain types of destinations be reachable. For example you might want the size of the coffee to only be a number symbolizing how many ounces of coffee was requested. Laravel gives you quite a bit of flexibility about limiting the route parameters to be conforming to only specific patterns. One way of constraining what the route parameter can be is to use Regular Expression constraint attached to the end of the route (listing 3.9):

Listing 3.9 Route with multiple parameters and with a constraint

// Constraining route parameter with a regular expression pattern
Route::get('coffee/{kind}/{size}', function($kind, $size)
{
  return 'Kind of coffee drink: '.$kind.', size: '.$size.'oz';
})->where('size', '[0-9]+');

Now if you try to go to this URL : coffee/espresso/tall you will encounter a “route not found” error. That is because you are using a route constraint limiting the “size” parameter to only numbers. Try reaching a different URL, coffee/espresso/24, that should work and you should see route response like in figure 3.8:

Figure 3.8 Reaching route with a constraint

Figure 3.8 Reaching route with a constraint

This can be helpful to filter out unwanted types of route parameters to be reached. Patterns like only numbers, only letters, combination of the two, and many more can be created with simple regular expression constraints.

3.13.3 Making route parameters optional

Not all route parameters are always necessary. There might be a case when a route parameter is optional. For example you would like to have the size of the coffee drink to be optional and not required. You can place a question mark (‘?’) after the route parameter and provide the default value for the matching variable to make that parameter optional (listing 3.10):

Listing 3.10 Route with an optional parameter for the size of the coffee

// Making a parameter optional by adding “?” after it and setting 
// a default value for it in the function arguments
Route::get('coffee/{kind}/{size?}', function($kind, $size = null)
{
  return 'Kind of coffee drink: '.$kind.', size: '.$size;
});

The optional parameter’s default value does not have to be a null value. You can set it to be anything, for example ‘tall’ or ‘12’. This way your application will not break when the user goes to URLs like:

  • coffee/espresso
  • coffee/espresso/grande
  • coffee/espresso/16
  • coffee/cappuccino
  • coffee/cappuccino/verylargesize

All of these URLs will work and the application will respond with the kind and the size of the coffee that the user has requested.

Using route parameters with constraints can be very powerful, flexible and dynamic. You can’t do without these instruments when you are building applications that have different types of data, APIs or some sort of interaction between the user and your application. What if you wanted to make your routing even more flexible, say you wanted to check that the size of the coffee drink can be only between 12 to 24 oz? Or if you wanted for some routes to be accessible only if the user is logged in? Another routing device up the Laravel’s sleeve is to the rescue in those cases. Dear reader, please welcome: Route Filters.

3.14 Route Filters

Route filters serve a purpose of filtering anything that deals with the application’s routes, data coming to and from the routes, route parameters, user permissions and more. They are small functions that when attached to routes allow you to fine tune what can be executed in different parts of your application. Route filters are conveniently located in “app/filters.php” file.

Route filters are great for building a basic implementation of an access control list, a technique of managing user’s access permissions. In fact, Laravel already comes with a few basic filters that can help you distinguish between users that are authenticated and logged in into your application, and the ones that are not authenticated – “guests”.

 Please note
Unless the filters are attached to the routes, they will not be executed.

Let’s look through the filters that Laravel provides out of the box and in the next section we will learn how to activate them. You can see these predefined route filters when you open up a fresh “app/filters.php” file of a new Laravel installation (listing 3.11):

Listing 3.11 Contents of fresh app/filters.php file

<?php

// Global filters that are executed at the beginning and at the end of 
// every request to the application
App::before(function($request) {});					
App::after(function($request, $response) {});				

// Filter that prevents users that are not logged in from accessing the 
// content of the application
Route::filter('auth', function()						
{
  if (Auth::guest()) return Redirect::guest('login');
});

// Filter that enables the use of basic authentication (great for building API’s)
Route::filter('auth.basic', function()					
{
  return Auth::basic();
});

// Filter that prevents logged in users from seeing pages that are 
// strictly meant for logged in users
Route::filter('guest', function()						
{
  if (Auth::check()) return Redirect::to('/');
});

// Filter that compares CSRF tokens on form submission, a useful security feature
Route::filter('csrf', function()						
{
  if (Session::token() != Input::get('_token'))
  {
    throw new IlluminateSessionTokenMismatchException;
  }
});

These filters might serve as the basis for your application’s security implementations. In most cases these default filters are enough to protect certain application routes from unauthorized use, but as you will see soon, you are not limited to using only what Laravel provides. First though, filters need to be attached to the routes to be activated, let’s look at how that could be done.

3.14.1 Attaching filters to routes

You can activate route filters by attaching them to the application’s routes. Filters can be executed before route’s execution (for example to prevent unauthorized access) or after (for example to log something). The diagram in figure 3.9 shows in which order the execution will take place:

Figure 3.9 Order of execution of route filters relative to the route

Figure 3.9 Order of execution of route filters relative to the route

The process of attaching a filter to any route in your application consists of two decisions:

  1. Deciding whether the filter should be executed before or after route’s execution
  2. Specifying which filter from “app/filters.php” you want to attach

To better understand the concept of attaching the filters to routes let’s look at simple real life example that shows this concept in action. Let’s imagine that you want only logged-in users to be able to access application’s route for ‘coffee’, while the guest users trying to access that same route will be taken to the login page. To attach the “auth” filter to the route that leads to “coffee” for the purpose of allowing to view the page for logged in users only, you would do it as follows in listing 3.12:

Listing 3.12 Attaching ‘auth’ filter to route ‘coffee’

// The ‘auth’ filter will be executed before the contents of the route is executed
Route::get('coffee', array('before' => 'auth', function()
{
  // Hello page will be only visible to logged in users
  return View::make('hello');
}));

Now if you try to reach the “coffee” route in the browser you will be redirected to the “login” route instead because the “auth” filter in “app/filters.php” file checks if the user is logged in, and if that condition is not met, it redirects the user to the “login” route and is not executing the contents of the “coffee” route.

You might have noticed that the structure for the route that has a filter attached has changed a bit comparing to the basic route structure you saw in figure 3.2. Route’s closure function is now inside of an array which is the second parameter of Laravel’s “Route::get” function.

We will learn more details about securing your application in later chapters of the book, but this basic concept of attaching route filters such as “auth” is enough to introduce you to the next concept of route filters – creating custom filters!

3.14.2 Creating custom filters

Remember, in our barista application from the section 3.2.3 we wanted to somehow check if the parameter passed to the route as the size of the drink (“coffee/espresso/24”) was within certain limits? In this section we will explore how you can enforce that limit and in the process you will learn how to create your own route filters.

Laravel allows you to create custom route filters painlessly. In order to attach a custom filter to any of your routes, first you have to define the new filter in “app/filters.php” file. Then after that filter is defined, you would attach it to a route as any of the Laravel’s built in filters.

Let’s create a filter that will check if the third route parameter is within defined limits, call it ‘checksize’, and if the parameter is not within limit of 12 – 24, we will tell the user that the passed parameter is out of allowed range. Add the following filter to “app/filters.php” (listing 3.13):

Listing 3.13 Custom filter added to filters.php

Route::filter('csrf', function(){ ... });
... 
// Define a new ‘checksize’ filter
Route::filter('checksize', function()					
{
  // Retrieve the third parameter of the route representing the size of the drink
  $size = Request::segment(3);						
  if($size < 12 || $size > 24)		
  {
    // Display an error in case the parameter is out of range
    return 'Size is not in the allowed range of 12 - 24';			
  }
});

Now that the filter is created, the only thing left is to attach it to the route from listing 3.10. We can do that by specifying the ‘checksize’ filter as the ‘before’ filter (listing 3.14):

Listing 3.14 Attaching custom filter to a route

// Filter ‘checksize’ attached to be executed before the route is executed
Route::get('coffee/{kind}/{size?}', array('before'=>'checksize',    	
  function($kind, $size = null)
  {
    return 'Kind of coffee drink: '.$kind.', size: '.$size;
  }
));

Try going to this route in the browser and make the size parameter (third parameter) bigger than our imposed limit of 24, you should see a page with the filter-specified error message (figure 3.10):

Figure 3.10 Showing an error message from a filter

Figure 3.10 Showing an error message from a filter

With this custom filter in place, the user will only be able to access the drinks that have sizes in range 12-24, thus our goal of limiting the passed route parameters to a certain range has been achieved.

3.14.3 Adding multiple route filters

Laravel doesn’t stop you from using more than one filter on any of your routes. For example you want to apply the size limit AND make the route accessible only to the users that are logged in. You can easily attach two, three or many more route filters by separating them with a pipe character “|” like in listing 3.15:

Listing 3.15 Attaching multiple filters to a route

// Multiple route filters are separated with “|”
Route::get('coffee/{kind}/{size?}', array('before'=> 'checksize|auth',					
  function($kind, $size = null)
  {
    return 'Kind of coffee drink: '.$kind.', size: '.$size;
  }
));

This way our coffee shop barista application will first check the size provided by the user using the ‘checksize’ filter and if the size is within allowed range, it will check if the user is logged in or not by executing the ‘auth’ filter. Implementing all sorts of access limiting couldn’t get easier than this by means of using multiple route filters.

3.15 Grouping routes

Sometimes when your application grows in size the routing file could also expand significantly. To prevent yourself from cluttering the routing file you could optimize the routing by means of grouping and prefixing routes that start with a common pattern. Imagine that you are trying to build routes for an administration panel of your website. You might have multiple routes all of which start with ‘admin’ like in listing 3.16:

Listing 3.16 Routing for an admin panel without grouping

Route::get('admin/users', function(){ ... });
Route::get('admin/posts', function(){ ... });
Route::get('admin/comments', function(){ ... });

When you have some routes that share a common pattern like the example in the listing above, it is a good idea to separate these routes as a group. Grouping routes is be done by taking a pattern common to some of the routes in your routing file and making them into a separate group. Laravel’s “Route::group” method with a ‘prefix’ parameter specifying the prefix for the ‘admin’ route group will accomplish the same task as the routing in listing above. Let’s see how this is done in practice in listing 3.17:

Listing 3.17 Routing for an admin panel with grouping

// Prefixing the route group with ‘admin’
Route::group(array('prefix' => 'admin'), function()
{
  Route::get('users', function(){ ... });
  Route::get('posts', function(){ ... });
  Route::get('comments', function(){ ... });
});

Now all routes that start with ‘admin’ will be automatically mapped to the route group and going to the ‘admin/posts’ will still work the same way as it did in listing 3.16. The biggest advantage of using route groups is the ability to attach filters to the whole group in the same way you would do it with a single route. Let’s say you wanted the user to be logged in to see the admin side of the site, you could attach the ‘auth’ filter to the whole group of routes like in the listing 3.18:

Listing 3.18 Attaching a filter to route group

// Attaching ‘auth’ filter to the whole group of routes
Route::group(array('prefix' => 'admin', 'before' => 'auth'), function(){
  ...
});

This Laravel’s instrument makes it very convenient to manage multiple routes that share a same prefix and/or need the same route filters for a group of routes.

3.16 Route responses

As you have learned in the beginning of this chapter, all routes should lead to some sort of a destination in your application. These destinations could be one of the following:

  • Displaying something back to the user (HTML, text, etc)
  • Directing the flow of execution to another route (also called “redirecting”)
  • Passing the execution to a function of another class in the application (also called “Controller routing”)

In Laravel applications, it is absolutely necessary for the route to have a definite conclusion, otherwise your application will not execute properly. You might remember the diagram showing the structure of a basic route (provided again in figure 3.11):

Figure 3.11 Structure of a basic route

Figure 3.11 Structure of a basic route

As you see, the second parameter of a basic route is a function. As with any other PHP functions, to get a result from executing a function, there has to be a ‘return’ statement. In case with Laravel, this ‘return’ statement could look like the following (listing 3.19):

Listing 3.19 Examples of possible route responses

// Responding by showing a Blade template
return View::make('contact');
// OR
// Responding by displaying text
return 'Route response';
// OR
// Responding by redirecting to another route
return Redirect::to('tea');

There is another type or response not listed here – responding by passing the execution to controllers. We will look at that type of response in the chapter titled “Controllers”. But first, let’s look at each of these possible responses in more detail. We will look at the first of the possible resolutions of a route, displaying something back to the user.

3.16.1 Showing output

One of the simplest ways to show output to the user is to simply return a string of text. Let’s say you want to if your routes are working properly, you could do that easily by returning a string from the route, listing 3.20 provides an example of that:

3.20 Route showing a string of text to the user

Route::get('text', function()
{
  // When the route returns a string, it will be shown to the user
  return 'This is route response';
});

You don’t have to stop here. You can even display HTML pages by returning an HTML string instead of plain text (listing 3.21).

3.21 Route showing a HTML to the user

Route::get('html', function()
{
  // Display HTML to the user
  return '<b>This text is bold!</b>';
});

Displaying HTML pages like that is not the cleanest way to render web pages. Laravel provides much more convenient methods of building that HTML string with it’s “View::make” capabilities that keep your routes clean. We will look more into the “View” methods later, but as an example you can display HTML pages by first creating the view template (and placing it into “app/views”) folder and then calling “View::make” from your route response. Let’s look at listing 3.22 to see how it is done:

3.22 Displaying HTML by responding with “View::make” method

// Contents of app/views/page.blade.php
<!doctype html>								
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>HTML test</title>
</head>
<body>
  <b>This text is bold!</b>
  <p>It is inside of a template</p>
</body>
</html>

// Inside of app/routes.php
Route::get('html', function()
{ 
  // Display HTML from a template by calling Laravel View methods
  return View::make('page');						
});

Now going to the ‘html’ route of your application will display a plain html page with the contents you specified in the view template.

These are the basic ways to show something back to the user, but what if you wanted to take the user to another page inside of your application, for example to the login page if the user is not logged in? Laravel provides you with a nice feature called “redirects” that can do exactly that.

3.16.2 Redirects

Redirects are convenient when you want to direct the user to another route within your application. This technique is often used to create a desired flow in an application. We have discussed route filters in section 3.3 of this chapter and you might have noticed redirects being used in some of the filters that Laravel is shipped with in the “app/filters.php” file. One of the filters we used was the “auth” filter and here is a reminder how it looked like (listing 3.23):

Listing 3.23 Auth filter is implementing a redirect

Route::filter('auth', function()
{
  // Redirecting the user to login page if not logged in
  if (Auth::guest()) return Redirect::guest('login');
});

To the user redirects simply make it look like they just went straight to the destination of the redirect. Laravel provides a few ways of using this simple yet efficient technique:

  • Redirecting to another URL inside of your application
  • Redirecting to a named route
  • Redirecting to a function inside of a class (controller)

We will look at the first two ways of redirects here and the third one will be discussed in the “Controllers” chapter.

3.16.2.1 Redirecting to other URLs inside of the application

Redirecting to any URL inside of your application could be done by returning a “Redirect::to” method, for example in listing 3.24 we will redirect the user to the page with the URL of “tea” when they access the “coffee” URL:

Listing 3.24 Redirecting the user to another URL inside of the application

Route::get('coffee', function()
{
  // Redirecting the user to URL “tea” relative to your application
  return Redirect::to('tea');						
});

Now if you try to access “coffee” URL you will immediately see your browser change the URL to “tea” which is what you would expect. You are not limited to just simple URLs, you can do more complex URLs just as successfully (listing 3.25):

Listing 3.25 Redirecting the user to a long URL inside of the application

Route::get('coffee', function()
{
  return Redirect::to('tea/black/earl-grey');				
});

As long as you have your routing defined for the target URLs, the user will be redirected to them. Another way to redirect to URLs inside the application is to redirect to named routes.

3.16.2.2 Redirecting to named routes

Laravel allows you to name your routes for convenience. If you had named any of your routes, you could redirect to them using Laravel’s “Redirect::route” method providing the name of the route to redirect to. For example, the code in listing 3.26 upon going to “coffee” URL will redirect the user to a route named as ‘tea’ and will show a text string telling which route it is:

Listing 3.26 Redirecting the user to a named route

Route::get('coffee', function()
{
  // Redirecting to a named route
  return Redirect::route('tea');						
});

// Naming the ‘this-is-tea’ route as ‘tea’
Route::get('this-is-tea', array('as' => 'tea', function()			
{
  return 'I am the tea route';
}));

This could be useful when you have many routes that don’t have expressive names and you would like to keep the structure of the routing cleaner.

3.17 Summary

The importance of this chapter cannot be underestimated. Routing defines the underlying behavior of your applications and without it Laravel applications simply would not function. You have learned how to create basic routes and how to get something out of them. You have explored the different types of routes and have applied the learned concepts by creating a simple HTML form that submits data to your Laravel application. Now you know how to pass parameters to the routes, how protect them using route filters and how to construct the desired behavior for your application.

In the next chapter you will learn in detail how to work with Laravel’s view templates and how to apply the knowledge you have already gained to make your pages more informative and management of them easier and enjoyable.

Liked it? Take a second to support Maks Surguy on Patreon!
Become a patron at Patreon!

You may also like

One comment

Leave a comment