Unconventional Laravel: Route groups and `$router`

When registering grouped routes using `Route::group()`, it's normal to register those nested routes using the `Route` facade, but have you ever used the `$router` variable?

Published 4 weeks ago | Updated 2 weeks ago
Laravel

This article is part of the Unconventional Laravel series.

  1. Auto-validating models
  2. Synchronous jobs for reusability
  3. Route groups and `$router`

I'd estimate that 99% of Laravel applications register their routes using the Illuminate\Support\Facades\Route class. It looks a little something like:

use Illuminate\Support\Facades\Route;

Route::get('/projects', 'ProjectsController@index');

The official documentation tells you this is the way to register routes and most applications use this method.

Route groups

A route group is a way of collecting a number of routes and assigning the same properties, or options, to them. For example, you could prefix a group of routes with the same url:

Route::prefix('/projects')->group(function () {
    Route::get('/', 'ProjectsController@index');
    Route::get('/{project}', 'ProjectsController@show');
});

This is a super convenient way of reducing the amount of duplication you would get from individually registering routes with that /projects prefix.

But did you know that you can drop the use of the Route facade inside of the group callback and make use of a $router parameter instead?

The $router parameter

The Closure that is passed to the group() method can actually take an argument. I tend to call it $router but you can call it whatever you want. So taking the previous example of a route group, you can do this:

Route::prefix('/projects')->group(function ($router) {
    $router->get('/', 'ProjectsController@index');
    $router->get('/{project}', 'ProjectsController@show');
});

If you wanted to type-hint parameter, you should type hint the Illuminate\Routing\Router class. The line of code responsible can be found here.

Pros & Cons

To be honest, there aren't really any big pros or cons to this approach. It's more of a "Did you know you could do this?" one.

Some people might think that there is a performance benefit since you're not calling a method on the Route facade each time, but after testing this with 100 routes the difference was literally a couple of milliseconds. This would be down to the fact that, under the hood, Laravel caches the underlying instance so that it doesn't need to be resolved from the container each time.

Sign off

If you've ever seen or used this approach before, I'd love to know on Twitter.

Thanks for reading 👋