Middleware Usage
Write a middleware class
Create a class in your module's Middlewares namespace and extend Quantum\Middleware\Middleware.
namespace App\Blog\Middlewares;
use Closure;
use Quantum\Http\Request;
use Quantum\Http\Response;
use Quantum\Middleware\Middleware;
final class RequireEditor extends Middleware
{
public function __construct(private Request $request)
{
}
public function apply(Request $request, Closure $next): Response
{
if (!auth()->check() || !in_array(auth()->user()->role, ['admin', 'editor'], true)) {
return redirect('/signin');
}
return $next($request);
}
}role is a field of your user. auth()->user() exposes the fields that the user schema marks visible, see the user schema contract.
The constructor example matters because the manager instantiates middleware with the current request before apply() runs.
Continue or stop
The basic decision inside apply() is simple:
- return
$next($request)when the request may continue - return your own
Responsewhen the request should stop here
A common pattern is to validate first and only continue on success.
public function apply(Request $request, Closure $next): Response
{
if (!$request->has('token')) {
return response()->json([
'message' => 'Missing token',
], 400);
}
return $next($request);
}Understand execution order
Middleware runs in route order.
If a route lists multiple middleware names, the first one gets the first chance to stop or modify the request. Later middleware run when earlier middleware call $next(...).
Group middleware wraps route-specific middleware. This is the usual shape for shared access checks plus route-level refinements.
$route->group('account', function ($route) {
$route->get('profile', 'AccountController', 'profile');
$route->post('avatar', 'AccountController', 'avatar')
->middlewares(['VerifiedUser']);
})->middlewares(['Auth']);With this setup, Auth runs before VerifiedUser.
Know what the package resolves
The manager does not look in the container and does not resolve middleware by alias.
Make sure:
- the class exists under the current module's
Middlewaresnamespace - the route middleware name matches the class suffix exactly
- the class extends
Quantum\Middleware\Middleware - any constructor you define accepts the current
Request
Keep rate limiting in mind
If the route also has a rate-limit definition, Quantum runs rate limiting before your module middleware.
That means your custom middleware may never run when the request is already rejected by the rate-limit stage.
Good fit for this package
Use middleware for request-level gates such as:
- authentication and guest checks
- ownership and role checks
- request preconditions
- early redirects or early API error responses
Avoid putting long business workflows here. The package is built for request flow control around a route handler.
