On this page
Caution
The documentation you are viewing is for an older version of this component.
Switch to the latest (v4) version.
Reference
Executing and composing middleware
The easiest way to execute middleware is to write closures and attach them to a
Laminas\Stratigility\MiddlewarePipe
instance. You can nest MiddlewarePipe
instances to create groups of related middleware, and attach them using a base
path so they only execute if that path is matched.
$api = new MiddlewarePipe(); // API middleware collection
$api->pipe(/* ... */); // repeat as necessary
$app = new MiddlewarePipe(); // Middleware representing the application
$app->pipe(new PathMiddlewareDecorator('/api', $api)); // API middleware attached to the path "/api"
Request path changes when path matched
When you use the
PathMiddlewareDecorator
using a path (other than '' or '/'), the middleware it decorates is dispatched with a request that strips the matched segment(s) from the start of the path. Using the previous example, if the path/api/users/foo
is matched, the$api
middleware will receive a request with the path/users/foo
. This allows middleware segregated by path to be re-used without changes to its own internal routing.
Handling errors
While the above will give you a basic application, it has no error handling
whatsoever. We recommend adding an initial middleware layer using the
Laminas\Stratigility\Middleware\ErrorHandler
class:
use Laminas\Diactoros\Response;
use Laminas\Stratigility\Middleware\ErrorHandler;
$app->pipe(new ErrorHandler(new Response());
// Add more middleware...
You can learn how to customize the error handler to your needs in the chapter on error handlers.
Decorating the MiddlewarePipe
Another approach is to compose a Laminas\Stratigility\MiddlewarePipe
instance
within your own Psr\Http\Server\MiddlewareInterface
implementation, and
optionally implementing the RequestHandlerInterface
and/or pipe()
method.
In such a case, you might define the process()
method to perform any
additional logic you have, and then call on the decorated MiddlewarePipe
instance in order to iterate through your stack of middleware:
class CustomMiddleware implements MiddlewareInterface
{
private $pipeline;
public function __construct(MiddlewarePipe $pipeline)
{
$this->pipeline = $pipeline;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
// perform some work...
// delegate to parent
$this->pipeline->process($request, $handler);
// maybe do more work?
}
}
Another approach using this method would be to override the constructor to add in specific middleware, perhaps using configuration provided.
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Laminas\Stratigility\MiddlewarePipe;
class CustomMiddleware implements MiddlewareInterface
{
private $pipeline;
public function __construct(array $configuration, MiddlewarePipe $pipeline)
{
// do something with configuration ...
// attach some middleware ...
$pipeline->pipe(/* some middleware */);
$this->pipeline = $pipeline;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
{
/* ... */
}
}
These approaches are particularly suited for cases where you may want to implement a specific workflow for an application segment using existing middleware, but do not necessarily want that middleware applied to all requests in the application.