MiddlewareInterface
The PSR-15-style contract for a single middleware step: `process(MessageInterface $message,
MessageHandlerInterface $handler): ResultInterface`. Implementations decide whether/when to call
$handler->handle() and can act on the message or result before/after doing so.
MiddlewarePipelineInterface / MiddlewarePipe
MiddlewarePipelineInterface extends both MiddlewareInterface and MessageHandlerInterface, and adds
pipe(MiddlewareInterface $middleware): void for registering middleware.
MiddlewarePipe is the default implementation, backed by an SplQueue. Calling handle() runs the
queued middleware against an EmptyPipelineHandler as the terminal handler (see below). Cloning a
MiddlewarePipe performs a deep clone of its internal queue so pipelines can be reused safely.
Next
Internal, single-use handler that walks the middleware queue one step at a time. Each call to handle()
dequeues the next middleware, clones itself for the remaining queue, and invokes the middleware with
that clone as its $handler. Once the queue is exhausted it delegates to the configured
EmptyPipelineHandler. Calling handle() on the same Next instance twice throws
Exception\NextHandlerAlreadyCalledException.
Middleware\MessageHandlerMiddleware
The library's built-in "terminal" middleware, registered by ConfigProvider with the lowest default
priority so it runs last. It uses a MessageHandlerResolverInterface to resolve and invoke the handler
mapped to the incoming message, then forwards the resulting ResultInterface on to the next handler in
the pipeline so any middleware that runs after it (e.g. logging) can inspect the result.
Handler\EmptyPipelineHandler
The default terminal handler used when a MiddlewarePipe's queue is exhausted. If the message it
receives is already a ResultInterface (i.e. a result produced by MessageHandlerMiddleware), it
returns it as-is; otherwise it throws Exception\MessageException, since no handler ever produced a
result.