It’s unfortunate that Laravel doesn’t provide conditional middleware out of the box. While there are workarounds—such as writing conditions directly in middleware or splitting route definitions—these approaches may not be ideal for every project.
To address this, I created a generic middleware proxy that allows you to apply another middleware conditionally based on route parameters:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class ConditionalParameterMiddleware
{
/**
* Handle an incoming request and conditionally apply a middleware.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string $condition Format: param=value
* @param string $middlewareAliasID Alias defined in Kernel
* @param mixed ...$middlewareArgs Additional arguments for the target middleware
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next, string $condition, string $middlewareAliasID, ...$middlewareArgs): Response
{
// Split condition string into parameter name and expected value
$separated = explode('=', $condition, 2);
if (count($separated) !== 2) {
Log::warning("Invalid condition format '{$condition}' in ConditionalParameterMiddleware.");
return $next($request);
}
[$paramName, $expectedValue] = $separated;
// Check if route parameter matches the expected value
if ($request->route($paramName) == $expectedValue) {
// Retrieve actual middleware class from Kernel aliases
$middlewareClass = app(\App\Http\Kernel::class)->getMiddlewareAliases()[$middlewareAliasID] ?? null;
if ($middlewareClass) {
$middlewareInstance = app($middlewareClass);
return $middlewareInstance->handle($request, $next, ...$middlewareArgs);
}
Log::warning("Middleware alias ID '{$middlewareAliasID}' not found in Kernel middleware aliases.");
}
return $next($request);
}
}
Example Usage
Assuming you have registered the conditional middleware alias in your `Kernel.php`:
protected $middlewareAliases = [
'conditional' => \App\Http\Middleware\ConditionalParameterMiddleware::class,
'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class,
];
You can then use it in a route like this:
Route::match(['get', 'post'], 'self/{section?}', [MyController::class, 'form'])
->middleware('conditional:section=mysection,verified')
->name('my.route');
In this example, the verified middleware will only be applied if the route parameter section equals mysection.