MiddlewarePipeline
MiddlewarePipeline builds and caches the PSR-15 middleware chain; safe for worker reuse.
Worker reuse is the part with teeth for anyone writing a middleware: the stack is built once per worker process and every instance in it then serves every request that worker handles, however many users those come from. A middleware is therefore process-scoped, not request-scoped, whatever the usual PSR-15 mental model suggests — so a $this->currentUser = $request-> getAttribute(...), or a $this->cached ??= lookup() memo of anything user-specific, is read back by the next request on that worker and hands one caller another caller’s data.
Keep request-scoped values on the request’s attribute bag or resolve them per call from the container; reserve instance properties for what is genuinely process-wide (config, a shared connection, a compiled table). A middleware that must hold per-request state anyway can implement ResetInterface, and MiddlewarePipeline::resetInstances() clears it at every request boundary.
Synopsis
Section titled “Synopsis”class MiddlewarePipeline implements RequestHandlerInterface
| Implements | RequestHandlerInterface |
| Source | Middleware/MiddlewarePipeline.php |
Constructor
Section titled “Constructor”__construct()
Section titled “__construct()”public function __construct(Context $context): mixed
| Parameter | Type | Description |
|---|---|---|
$context | Context |
Returns mixed
Methods
Section titled “Methods”| Method | Description |
|---|---|
coreMiddlewareClasses(): list<class-string<MiddlewareInterface>> | The framework’s own shipped middleware classes. |
debugStack(): list<string> | |
guardedMiddlewareClasses(): list<string> | The full set MiddlewareConfigRegistry guards against silent config-driven reordering or disabling. |
handle(ServerRequestInterface $request): ResponseInterface | Runs the request through the middleware stack, building the stack first if needed. |
protectedPackageMiddlewareClasses(): list<string> | First-party middleware that ships in its own package rather than being built by core. |
reset(): void | Discards the cached stack so the next MiddlewarePipeline::handle() rebuilds it. |
resetInstances(): void | Clears the per-request state of every middleware in the built stack that declares any, by calling ResetInterface::reset() on it. |
coreMiddlewareClasses()
Section titled “coreMiddlewareClasses()”public static function coreMiddlewareClasses(): list<class-string<MiddlewareInterface>>
The framework’s own shipped middleware classes.
Returns list``<``class-string``<MiddlewareInterface>``>
debugStack()
Section titled “debugStack()”public function debugStack(): list<string>
Returns list``<``string``>
guardedMiddlewareClasses()
Section titled “guardedMiddlewareClasses()”public static function guardedMiddlewareClasses(): list<string>
The full set MiddlewareConfigRegistry guards against silent config-driven reordering or disabling.
Returns list``<``string``>
handle()
Section titled “handle()”public function handle(ServerRequestInterface $request): ResponseInterface
Runs the request through the middleware stack, building the stack first if needed.
The built stack is cached on the instance for the life of the worker, so only the first request pays for attribute scanning and order resolution; call MiddlewarePipeline::reset() to force a rebuild.
| Parameter | Type | Description |
|---|---|---|
$request | ServerRequestInterface |
Returns ResponseInterface
| Throws | When |
|---|---|
QuioteException | If building the stack produced no handler. |
protectedPackageMiddlewareClasses()
Section titled “protectedPackageMiddlewareClasses()”public static function protectedPackageMiddlewareClasses(): list<string>
First-party middleware that ships in its own package rather than being built by core.
Returns list``<``string``>
reset()
Section titled “reset()”public function reset(): void
Discards the cached stack so the next MiddlewarePipeline::handle() rebuilds it.
Needed whenever the inputs to the build have changed — a catalog registration, a middleware config entry, an enable/disable override — since the stack is otherwise kept for the worker’s lifetime. The middleware instances themselves are dropped, not reset.
resetInstances()
Section titled “resetInstances()”public function resetInstances(): void
Clears the per-request state of every middleware in the built stack that declares any, by calling ResetInterface::reset() on it.
The stack itself is kept — this is the request boundary, not a rebuild.
Run for each request in a persistent worker, where the instances outlive the request that populated them. A middleware that keeps nothing between calls (the norm, and what MiddlewarePipeline asks for) implements nothing and is skipped.