zendframework/zend-stratigility
Zend Stratigility is a lightweight middleware pipeline for PHP, built around PSR-7 HTTP messages. Compose request/response processing with reusable middleware, route-like piping, and error handling—ideal for building microservices or adding middleware to existing apps.
In your application, you may need to handle error conditions:
You can typically handle these conditions via middleware itself.
If no middleware is able to handle the incoming request, this is typically
representative of an HTTP 404 status. Stratigility provides a barebones
middleware that you may register in an innermost layer that will return a 404
condition, Zend\Stratigility\Middleware\NotFoundHandler. The class requires a
response prototype instance that it will use to provide the 404 status and a
message indicating the request method and URI used:
// setup layers
$app->pipe(/* ... */);
$app->pipe(/* ... */);
$app->pipe(new NotFoundHandler(new Response());
// execute application
Note that it is the last middleware piped into the application! Since it returns a response, no deeper nested layers will execute once it has been invoked.
If you would like a templated response, you will need to write your own middleware; such middleware might look like the following:
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface as ServerMiddlewareInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class NotFoundMiddleware implements ServerMiddlewareInterface
{
private $renderer;
public function __construct(
TemplateRendererInterface $renderer,
ResponseInterface $response
) {
$this->renderer = $renderer;
$this->response = $response;
}
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
$response = $this->response->withStatus(404);
$response->getBody()->write(
$this->renderer->render('error::404')
);
return $response;
}
}
Zend\Stratigility\Middleware\ErrorHandler is a middleware implementation to
register as the outermost layer of your application (or close to the outermost
layer). It does the following:
error_handling()
mask and throws them as ErrorException instances.To generate the error response, we provide the ability to inject a callable with
the following signature into the ErrorHandler during instantiation:
Psr\Http\Message\ResponseInterface;
Psr\Http\Message\ServerRequestInterface;
function (
Throwable|Exception $e,
ServerRequestInterface $request,
ResponseInterface $response
) : ResponseInterface
We provide a default implementation, Zend\Stratigility\Middleware\ErrorResponseGenerator,
which generates an error response with a 5XX series status code and a message
derived from the reason phrase, if any is present. You may pass a boolean flag
to its constructor indicating the application is in development mode; if so, the
response will have the stack trace included in the body.
In order to work, the ErrorHandler needs a prototype response instance, and,
optionally, an error response generator (if none is provided,
ErrorResponseGenerator is used, in production mode):
// setup error handling
$app->pipe(new ErrorHandler(new Response(), new ErrorResponseGenerator($isDevelopmentMode));
// setup layers
$app->pipe(/* ... */);
$app->pipe(/* ... */);
As a full example, you can combine the two middleware into the same application as separate layers:
// setup error handling
$app->pipe(new ErrorHandler(new Response(), new ErrorResponseGenerator($isDevelopmentMode));
// setup layers
$app->pipe(/* ... */);
$app->pipe(/* ... */);
// setup 404 handling
$app->pipe(new NotFoundHandler(new Response());
// execute application
The ErrorResponseGenerator provides no templating facilities, and only
responds as text/html. If you want to provide a templated response, or a
different serialization and/or markup format, you will need to write your own
error response generator.
As an example:
use ErrorException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Throwable;
use Zend\Stratigility\Exception\MissingResponseException;
use Zend\Stratigility\Middleware\ErrorHandler;
class TemplatedErrorResponseGenerator
{
private $isDevelopmentMode;
private $renderer;
public function __construct(
TemplateRendererInterface $renderer,
$isDevelopmentMode = false
) {
$this->renderer = $renderer;
$this->isDevelopmentMode = $isDevelopmentMode;
}
public function __invoke($e, ServerRequestInterface $request, ResponseInterface $response)
{
$response = $response->withStatus(500);
$response->getBody()->write($this->renderer->render('error::error', [
'exception' => $e,
'development_mode' => $this->isDevelopmentMode,
]));
return $response;
}
}
You would then pass this to the ErrorHandler:
$app->pipe(new ErrorHandler(
new Response(),
new TemplatedErrorResponseGenerator($renderer, $isDevelopmentMode)
));
Zend\Stratigility\Middleware\ErrorHandler provides the ability to attach
listeners; these are triggered when an error or exception is caught, and
provided with the exception/throwable raised, the original request, and the
final response. These instances are considered immutable, so listeners are for
purposes of logging/monitoring only.
Listeners must implement the following signature:
Psr\Http\Message\ResponseInterface;
Psr\Http\Message\ServerRequestInterface;
function (
Throwable|Exception $e,
ServerRequestInterface $request,
ResponseInterface $response
) : void
Attach listeners using ErrorHandler::attachListener():
$errorHandler->attachListener(function ($throwable, $request, $response) use ($logger) {
$message = sprintf(
'[%s] %s %s: %s',
date('Y-m-d H:i:s'),
$request->getMethod(),
(string) $request->getUri(),
$throwable->getMessage()
);
$logger->error($message);
});
How can I help you explore Laravel packages today?