Declaring multiple parameters in a Laravel Route, all this parameters must be included in the action method, even if some of this parameter are not used in the method.
For example, in this web routes:
Route::get('post/{slug}/{uuid}', PostController::class);
In the Controller only the uuid
parameter is needed to fetch the Post, but the parameter slug
must also be present.
class PostController
{
public function __invoke(string $slug, string $uuid, Request $request)
{
$post = Post::where('uuid', $uuid)->findOrFail();
//...
}
}
Solution
The solution to skip requiring the slug
parameter, is by using a middleware, in which we tell the request to just forget any parameter we want.
class RouteArgumentsFilter
{
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
* @param string ...$parameters
*/
public function handle(Request $request, Closure $next, string ...$parameters): Response
{
array_map(
$request->route()->forgetParameter(...),
$parameters
);
return $next($request);
}
}
And the middleware, we specifiy to parameter to forget :slug
Route::get('post/{slug}/{uuid}', PostController::class)
->middleware(RouteArgumentsFilter::class . ':slug');
Now the Controller can be simplified:
class PostController
{
public function __invoke(string $uuid, Request $request)
{
$post = Post::where('uuid', $uuid)->findOrFail();
//...
}
}