This package provides an alternative to the default Slim error handler and renderer.
It renders a styled error details page with the stack trace and the error message
or a generic error page for production.
Custom error page renderers can be created to change the design of the error pages
by implementing the ErrorDetailsPageRendererInterface
or GenericErrorPageRendererInterface
.
It also provides a middleware to make the project "exception-heavy", which means that it will throw exceptions with a stack trace for notices and warnings during development and testing like other frameworks such as Laravel or Symfony.
Exception | Warning and Notice | Generic error page |
---|---|---|
- PHP 8.2+
- Composer
- A Slim 4 application
Open a terminal in your project's root directory and run the following command:
composer require samuelgfeller/slim-error-renderer
The following configuration values are required in the settings. Modify accordingly in the development, production, and testing configuration files.
File: config/defaults.php
$settings['error'] = [
// Must be set to false in production
'display_error_details' => false,
// Whether to log errors or not
'log_errors' => true,
];
If you're using
Dependency Injection,
add the error handling middleware to
the container definitions (e.g. in the config/container.php
) file.
The ExceptionHandlingMiddleware
constructor accepts the following parameters:
- Required: instance of a response factory object implementing the
Psr\Http\Message\ResponseFactoryInterface
(see here for a default implementation of a response factory) - Optional: instance of a PSR 3 logger to log the error
- Optional: boolean to display error details (documentation: Error Handling)
- Optional: contact email for the "report error" button on the error page
- Optional: A custom generic error page renderer that
implements
SlimErrorRenderer\Interfaces\ProdErrorPageRendererInterface
- Optional: A custom error details page renderer that
implements
SlimErrorRenderer\Interfaces\ErrorDetailsPageRendererInterface
<?php
use SlimErrorRenderer\Middleware\ExceptionHandlingMiddleware;
return [
// ...
ExceptionHandlingMiddleware::class => function (ContainerInterface $container) {
$settings = $container->get('settings');
$app = $container->get(App::class);
return new ExceptionHandlingMiddleware(
$app->getResponseFactory(),
$settings['error']['log_errors'] ? $container->get(LoggerInterface::class) : null,
$settings['error']['display_error_details'],
$settings['public']['main_contact_email'] ?? null
);
},
// ...
];
The middleware can now be added to the middleware stack in the config/middleware.php
file.
It should be the very last middleware in the stack to catch all exceptions (Slim middlewares
are executed in the
reverse order
they are added).
This replaces the default slim error middleware.
<?php
use Slim\App;
return function (App $app) {
// ...
// Handle exceptions and display error page
$app->add(ExceptionHandlingMiddleware::class);
}
The NonFatalErrorHandlingMiddleware
promotes warnings and notices to exceptions
when the display_error_details
setting is set to true
in the
configuration.
This means that the error details for notices and warnings will be displayed
with the stack trace and error message.
The NonFatalErrorHandlingMiddleware
also needs to be instantiated in the container.
The constructor takes three parameters:
- Required: bool to display error details
- Required: bool to log the warning / notice
- Optional: instance of a PSR 3 logger to log the warning / notice
<?php
use SlimErrorRenderer\Middleware\NonFatalErrorHandlingMiddleware;
return [
// ...
NonFatalErrorHandlingMiddleware::class => function (ContainerInterface $container) {
$settings = $container->get('settings');
return new NonFatalErrorHandlingMiddleware(
$settings['error']['display_error_details'],
$settings['error']['log_errors'] ? $container->get(LoggerInterface::class) : null,
);
},
// ...
];
The middleware should be added right above the ExceptionHandlingMiddleware
in
the stack.
File: config/middleware.php
use Slim\App;
return function (App $app) {
// ...
// Promote warnings and notices to exceptions
$app->add(NonFatalErrorHandlingMiddleware::class); // <- Add here
// Handle exceptions and display error page
$app->add(ExceptionHandlingMiddleware::class);
}
Have a look a the slim-starter
for a default
implementation of this package and the
slim-example-project
for a custom
prod error page with layout.
A reason this small library exists instead of using the default Slim error handler and a custom
error renderer,
is to provide the "exception-heavy" feature and better-looking error pages.
But these things can be achieved with a custom error renderer and middleware located in the project as well.
The issue with the default Slim\Handlers\ErrorHandler
is that while testing, the
$contentType
in the error handler is null
and instead of using any custom error renderer
its hardcoded to use the Slim\Error\Renderers\HtmlErrorRenderer
. This has two consequences:
- The error is not thrown while integration testing, which means debugging is harder.
- Tests where an exception is expected, fail with the
PHPUnit 11 warning
Test code or tested code did not remove its own error handlers
. A fix for this message is callingrestore_error_handler()
but this can't be done as the error handler doesn't allow for custom error renderers when testing.
So a custom handler is required anyway, and with the custom renderers and the handling of non-fatal errors, it made sense to put that in a separate small library.
This project is licensed under the MIT license — see the LICENSE file for details.