Expressive provides error handling out of the box, via zend-stratigility's FinalHandler implementation. This pseudo-middleware is executed in the following conditions:
- If the middleware stack is exhausted, and no middleware has returned a response.
- If an error has been passed via
$next(), but not handled by any error middleware.
FinalHandler essentially tries to recover gracefully. In the case that no error was passed, it
does the following:
- If the response passed to it differs from the response provided at initialization, it will return
the response directly; the assumption is that some middleware along the way called
$next()with a new response.
- If the response instances are identical, it checks to see if the body size has changed; if it has, the assumption is that a middleware at some point has written to the response body.
- At this point, it assumes no middleware was able to handle the request, and creates a 404 response, indicating "Not Found."
In the event that an error was passed, it does the following:
$erroris not an exception, it will use the response status if it already indicates an error (ie., >= 400 status), or will use a 500 status, and return the response directly with the reason phrase.
$erroris an exception, it will use the exception status if it already indicates an error (ie., >= 400 status), or will use a 500 status, and return the response directly with the reason phrase. If the
FinalHandlerwas initialized with an option indicating that it is in development mode, it writes the exception stack trace to the response body.
This workflow stays the same throughout zend-expressive. But sometimes, it's just not enough.
You'll typically want to provide error messages in your site template. To do so, we provide
Zend\Expressive\TemplatedErrorHandler. This class is similar to the
FinalHandler, but accepts,
Zend\Expressive\Template\TemplateRendererInterface instance, and template names to use for
404 and general error conditions. This makes it a good choice for use in production.
First, of course, you'll need to select a templating system and ensure you have the appropriate dependencies installed; see the templating documentation for information on what we support and how to install supported systems.
Once you have selected your templating system, you can setup the templated error handler.
use Zend\Expressive\Application; use Zend\Expressive\Plates\PlatesRenderer; use Zend\Expressive\TemplatedErrorHandler; $plates = new PlatesRenderer(); $plates->addPath(__DIR__ . '/templates/error', 'error'); $finalHandler = new TemplatedErrorHandler($plates, 'error::404', 'error::500'); $app = new Application($router, $container, $finalHandler);
The above will use the templates
error::500 for 404 and general errors,
respectively, rendering them using our Plates template adapter.
You can also use the
TemplatedErrorHandler as a substitute for the
FinalHandler, without using
templated capabilities, by omitting the
TemplateRendererInterface instance when instantiating it. In this
case, the response message bodies will be empty, though the response status will reflect the error.
See the section titled "Container Factories and Configuration", below, for techniques on configuring
TemplatedErrorHandler as your final handler within a container-based application.
whoops is a library for providing a more usable UI around
exceptions and PHP errors. We provide integration with this library through
Zend\Express\WhoopsErrorHandler. This error handler derives from the
uses its features for 404 status and non-exception errors. For exceptions, however, it will return
the whoops output. As such, it is a good choice for use in development.
To use it, you must first install whoops:
$ composer require filp/whoops
Then you will need to provide the error handler a whoops runtime instance, as well as a
Whoops\Handler\PrettyPageHandler instance. You can also optionally provide a
instance and template names, just as you would for a
use Whoops\Handler\PrettyPageHandler; use Whoops\Run as Whoops; use Zend\Expressive\Application; use Zend\Expressive\Plates\PlatesRenderer; use Zend\Expressive\WhoopsErrorHandler; $handler = new PrettyPageHandler(); $whoops = new Whoops; $whoops->writeToOutput(false); $whoops->allowQuit(false); $whoops->pushHandler($handler); $plates = new PlatesRenderer(); $plates->addPath(__DIR__ . '/templates/error', 'error'); $finalHandler = new WhoopsErrorHandler( $whoops, $handler, $plates, 'error::404', 'error::500' ); $app = new Application($router, $container, $finalHandler); // Register Whoops just before running the application, as otherwise it can // swallow bootstrap errors. $whoops->register(); $app->run();
The calls to
register() must be made to guarantee
whoops will interoperate well with zend-expressive.
You can add more handlers if desired.
Internally, when an exception is discovered, zend-expressive adds some data to the whoops output, primarily around the request information (URI, HTTP request method, route match attributes, etc.).
See the next section for techniques on configuring the
WhoopsErrorHandler as your final handler
within a container-based application.
Container Factories and Configuration
The above may feel like a bit much when creating your application. As such, we provide several factories that work with container-interop-compatible container implementations to simplify setup.
In each case, you should register the selected error handler's factory as the service
- For the
- For the