Routing is one of the core concepts in Laravel, and it works a little differently than some of the frameworks of the past. The Laravel Route system is very flexible. So, let’s dig into Laravel Routes!

What Is a Route in Laravel?

Route is a way of creating a request URL of your application. The best thing about these URLs is that you are free to define a route in whatever manner you wish for it to look like. Basically, they are readable and SEO friendly.

In Laravel >= 5.5, all requests are mapped with the help of routes, and routes are created inside the routes folder. Routes for the website are created in web.php  file, Similarly, the routes for the API are created inside api.php .

The default installation of Laravel 5.5 comes with two routes, one for the web and the other for API. Here is how the route for web in web.php  looks like:

Route::get('/', function () {
  return view('welcome');
});

In the above code, we have defined a route for the homepage. Every time this route receives a get request for /, It will return the view welcome.

The structure of a route definition is quite simple. In an appropriate file (either web.php or api.php) start the line with Route:: which is then followed by the request you want to assign to that specific route. The function that executes as a result of the request comes after that.

Laravel offers the following route methods:

  • get
  • post
  • put
  • delete
  • patch
  • options

which we can use as:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Routing with Controller Function

In Laravel, you can define a Controller method to a route. If a user comes to the route that has a controller method, the method of the defined controller will perform the actions.

To assign a controller method to the route, use the following code snippet:

Route::get('/home', '[email protected]');

The code starts with Route:: and then define the request method for the route. Next, define your route and then define the Controller along with the method that you want to bind to this route by adding the @ symbol before the method’s name.

Route Parameters

Now, let’s create a basic route that will print the sqaure of 2.

Route::get('/square/{number}', function($number) {
  echo $number * $number.
  "<br>";
});

In the above code, I defined a route parameter and passed it to the route function. Now, whenever a user route to /square  and add a number to the request (for instance, /square/3 ), the function will print the square of that number to the screen.

Optional Route Parameters with Default Parameter Values

Adding a ‘?  to the wildcard and assigning null to the closure argument will allow the parameter to be optional, otherwise, you’ll get an error if you don’t include the parameter. I will now do this for the above-mentioned example route:

Route::get('/square/{number?}', function($number = 2) {
  echo $number * $number.
  "<br>";
});

What we have done in the above code is that we have made our route parameter i.e. number optional so if a user route /square  only then square of 2 will be generated by default and if a user route to /square/{number} then the square of that number will be printed.

Regular Expression Constraints For Route Parameters

Above we have created a route for square, but how can we avoid getting an error while generating a square if the route parameter is a string? In Laravel, we can define a constraint for our route parameter by using where a method on route instance. The where the method takes parameter name and a regular expression rule for that parameter. Let’s now define a constraint for our {number} parameter to assure that only number is passed to the function.

Route::get('/square/{number?}', function($number = 2) {
  echo $number * $number.
  "<br>";
}) -> where('number', '[0-9]+');

In the above snippet, I defined a regular expression for our route’s number. Now if a user try to route to /square/string, system will display a NotFoundHttpException.

Naming Your Routes

A common convention in Laravel is naming routes which allows you to easily reference the name of the route, and avoid hard-coding URIs in templates. It is very useful: for example if you want to redirect a user from one route to another, you do not need to define the full redirect URL. Rather, you can just give its name and the code will work! You can define the name of the route by using the name method in the route instance

Route::get('/square/{number?}', function($number = 2) {
  echo $number * $number.
  "<br>";
}) -> name('square');

Thus, we could generate the URL for this route through:

$url = route('square');

Similarly, for redirecting to this URL, the proper syntax would be:

return redirect()->route('square');

Route Groups

Route groups allow you to share route properties, such as prefixes or middlewares, across a many routes without needing to define those properties on each individual route. Shared attributes are specified in an array format as the first parameter to the Route::group  method.

Route::group(function() {
  Route::get('/square/{number?}', function($number = 2) {
    echo $number * $number.
    "<br>";
  }) - > name('square');
  Route::get('/factorial/{number?}', function($number = 0) {
    $factorial = 1;
    for ($i = $number; $i >= 1; $i--) {
      $factorial *= $i;
    }
    echo "Factorial of $number is $factorial";
  }) - > name('factorial');
});

Once we have a group of routes, any method we chain to the group will be applied to all the routes inside that group. For example, we can add a prefix to a group of routes like so,

Route::prefix('math') - > group(function() {
  Route::get('/square/{number?}', function($number = 2) {
    echo $number * $number.
    "<br>";
  }) - > name(‘square’);
  Route::get('/factorial/{number?}', function($number = 0) {
    $factorial = 1;
    for ($i = $number; $i >= 1; $i--) {
      $factorial *= $i;
    }
    echo "Factorial of $number is $factorial";
  }) - > name(‘factorial’);
});

Thus, the above group will match request URIs like /math/square and /math/factorial .

Naming Group Routes

In some applications hard-coding the URI is fine, in other cases, the named routes allow the following:

{{route('math.factorial.show', ['number' => $number])}} 
{{--/admin/factorial / 2--}}

The name method may be used to prefix each route name in the group with a given string. For example, you may want to prefix all of the grouped route’s names with math. The given string is prefixed to the route name exactly as it is specified, so we will be sure to provide the trailing . character in the prefix:

Route::prefix('math') - > name('math.') - > group(function() {
  Route::get('/square/{number?}', function($number = 2) {
    echo $number * $number.
    "<br>";
  }) - > name(‘square’);
  Route::get('/factorial/{number?}', function($number = 0) {
    $factorial = 1;
    for ($i = $number; $i >= 1; $i--) {
      $factorial *= $i;
    }
    echo "Factorial of $number is $factorial";
  }) - > name(‘factorial’);
});

The above prefixed name would generate route names like the following:

  • math.square
  • math.factorial

Routing Namespaces

A common use-case for route groups is assigning the same PHP namespace to a group of controllers using the namespace method:

Route::namespace('Math') - > group(function() { 
// Controllers Within The "App\Http\Controllers\Math" Namespace});

Thus, in our “math” routing example, the routes definition in the routes/web.php  file might look like this:

Route::namespace('Math') - > prefix('math') - > name('math.') - > group(function() {
  Route::get('square/{number?}', '[email protected]');
  Route::get('factorial/{number?}', '[email protected]');
});

Reusable routes (Route Macros)

If you have a group of routes that you would like to reuse or provide in a Laravel package then Laravel makes it easy for you to do so with its macroable router. You can define a route macro in a service provider.

For example, we can have a group of math routes like we had in our examples that we ship as a package which allows users to override or customize some parts of the routes like:

// Inside a service provider 
boot() public

function boot() {
  Route::macro('mathRoutes', function($prefix) {
    Route::group(['prefix' => $prefix, 'name' => $prefix, ], function() {
      Route::get('square/{number?}', '[email protected]');
      Route::get('factorial/{number?}', '[email protected]') // ...       
    });
  });
}

Thus, now the user could call the macro in a new Laravel application within routes/web.php to use the math routes:

Route::mathRoutes('math');

If you find yourself repeating performing logic on Laravel components throughout your system, think about using a macro for better expression and reuse. Although if you want to add functionality to your own classes then you should simply add the methods you need or use traits, macros exist to add functionality to classes that you don’t own. if you are creating a custom Laravel package then it might be worth adding the trait to your classes to make it easy for your users to add functionality.

Conclusion

Laravel has a very powerful router and has made much customisation available for you to use.  To learn more about routing, you could also refer to the official Laravel routing documentation.