Follow on twitter
Jun 3rd, 2019

Removing parameters from routes in Laravel

How can we remove irrelevant arguments from the request when they were defined in the route?

<?php
Route::get('/{category}/{slug}-{id}', 'ArticleController@show');
class ArticleController
{
// public function show($category, $slug, $id)
public function show($id)
{
//
}
}
view raw 1.php hosted with ❤ by GitHub

If you are using Laravel, it is very likely that you know how to use regular expression constraints in your routes.

You may constrain the format of your route parameters using the where method on a route instance. The where() method accepts the name of the parameter and a regular expression defining how the parameter should be constrained.

These constraints allow defining a set of “filters” to make sure the right route captures every request.

Consider the following example:

<?php
Route::get('/{category}/{slug}-{id}', 'ArticleController@show');
view raw 2.php hosted with ❤ by GitHub

If we want to ensure the {id} contains only digits, we can do the following:

Route::get('/{category}/{slug}-{id}', 'ArticleController@view')
->where([
// One or more digits
'id' => '[\d]+'
]);
view raw 3.php hosted with ❤ by GitHub

Then, the show() method in the article controller receives the route parameters in the same order they were defined:

<?php
class ArticleController
{
public function show($category, $slug, $id)
{
return view('article')->withArticle(Article::find($id))
}
}
view raw 4.php hosted with ❤ by GitHub

As you can see, in this example the $category and $slug arguments are not relevant and won’t be used in the controller, so let’s see how to remove them from the request.

Removing route-arguments from the request

Let’s create a new middleware for this:

php artisan make:middleware RouteArgumentsFilterMiddleware

This is how the new middleware class code:

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Arr;
class RouteArgumentsFilterMiddleware
{
public function handle($request, Closure $next)
{
$config = config('route.filters');
if (Arr::has($config, $request->route()->getName())) {
foreach (Arr::get($config, $request->route()->getName()) as $argument) {
$request->route()->forgetParameter($argument);
}
}
return $next($request);
}
}
view raw 5.php hosted with ❤ by GitHub

Remember to Register the Middleware in your app/Http/kernel.php I’m using a new config file to register the arguments that I want to exclude for a specific route:

<?php
// config/route.php
return [
'filters' => [
// Route name
'article' => [
// Route arguments {name}
'category',
'slug'
]
]
];
view raw 6.php hosted with ❤ by GitHub

Now you can update the controller:

<?php
class ArticleController
{
public function show($id)
{
return view('article')->withArticle(Article::find($id))
}
}
view raw 7.php hosted with ❤ by GitHub

As the middleware is removing parameters from the current route, you are going to receive just the remaining parameters in your controllers, $id in this case.

Wrapping up

Please take into consideration that the situation described in this article is just an example, but there are some other cases where this approach would be a better fit.

This solution is especially helpful when you use Route Groups with a prefix, for instance.

Jeff
4 months ago
Share: