Makes handling and debugging PHP errors suck less.
Contents
normal / debug mode
converts PHP errors (warnings, notices, etc.) into exceptions
respects the global
error_reporting
settinghandles uncaught exceptions and fatal errors (including parse and out-of-memory errors)
CLI error screen writes errors to stderr
web error screen renders errors for web browsers
-
- file paths and line numbers
- highlighted code previews
- stack traces
- argument lists
- output buffer (can be shown as HTML too)
- plaintext trace (for copy-paste)
event system that can be utilised to:
- implement logging
- suppress or force errors conditionally
- change or add content to the error screens
- PHP 7.1+
<?php
use Kuria\Error\ErrorHandler;
$debug = true; // true during development, false in production
error_reporting(E_ALL); // configure the error reporting
$errorHandler = new ErrorHandler();
$errorHandler->setDebug($debug);
$errorHandler->register();
// trigger an error to see the error handler in action
echo $invalidVariable;
Possible events emitted by the ErrorHandler
class are listed in ErrorHandlerEvents
:
Emitted when a PHP errors occurs.
Arguments:
Kuria\Error\Exception\ErrorException $exception
- you may use the
suppress()
orforce()
method to suppress or force the exception, respectivelly, regardless of theerror_reporting
PHP setting
- you may use the
bool $debug
Emitted when an uncaught exception or a fatal error is being handled.
Arguments:
Throwable $exception
bool $debug
Warning
Avoid performing memory-intensive tasks in listeners of this event if
$exception
is an instance of Kuria\Error\Exception\OutOfMemoryException
.
Emitted when an uncaught exception or a fatal error could not be handled. This can happen
when an exception
event listener or the registered error screen throws an additional
exception. Throwing another exception or causing a fatal error at this point will just
kill the script.
Arguments:
Throwable $exception
bool $debug
Warning
Avoid performing memory-intensive tasks in listeners of this event if
$exception
is an instance of Kuria\Error\Exception\OutOfMemoryException
.
Possible events emitted by the WebErrorScreen
class are listed in WebErrorScreenEvents
:
Emitted when rendering in normal mode.
Receives an array with the following keys:
&title
: used in<title>
&heading
: used in<h1>
&text
: content of the default paragraph&extras
: custom HTML after the main sectionexception
: the exceptionoutput_buffer
: string|null
Emitted when rendering in debug mode.
Receives an array with the following keys:
&title
: used in<title>
&extras
: custom HTML after the main sectionexception
: the exceptionoutput_buffer
: string|null
Emitted when CSS styles are being output.
Receives a single boolean value indicating debug mode.
Emitted when JavaScript code is being output.
Receives a single boolean value indicating debug mode.
Possible events emitted by the CliErrorScreen
class are listed in CliErrorScreenEvents
:
Emitted when rendering in normal mode.
Receives an array with the following keys:
&title
: first line of output&output
: error messageexception
: the exceptionoutput_buffer
: string|null
Emitted when rendering in debug mode.
Receives an array with the following keys:ng keys:
&title
: first line of output&output
: error messageexception
: the exceptionoutput_buffer
: string|null
Logging uncaught exceptions into a file:
<?php
use Kuria\Debug\Error;
use Kuria\Error\ErrorHandlerEvents;
$errorHandler->on(ErrorHandlerEvents::EXCEPTION, function (\Throwable $exception, bool $debug) {
$logFilePath = sprintf('./errors_%s.log', $debug ? 'dev' : 'prod');
$entry = sprintf(
"[%s] %s: %s in file %s on line %d\n",
date('Y-m-d H:i:s'),
Error::getExceptionName($exception),
$exception->getMessage(),
$exception->getFile(),
$exception->getLine()
);
file_put_contents($logFilePath, $entry, FILE_APPEND | LOCK_EX);
});
This listener causes statements like echo @$invalidVariable;
to throw an exception regardless of the "shut-up" operator.
<?php
use Kuria\Error\Exception\ErrorException;
use Kuria\Error\ErrorHandlerEvents;
$errorHandler->on(ErrorHandlerEvents::ERROR, function (ErrorException $exception, bool $debug) {
$exception->force();
});
Note
Examples are for the WebErrorScreen
.
Changing default labels in normal mode:
<?php
use Kuria\Error\Screen\WebErrorScreen;
use Kuria\Error\Screen\WebErrorScreenEvents;
$errorScreen = $errorHandler->getErrorScreen();
if (!$errorHandler->isDebugEnabled() && $errorScreen instanceof WebErrorScreen) {
$errorScreen->on(WebErrorScreenEvents::RENDER, function ($event) {
$event['heading'] = 'It is all your fault!';
$event['text'] = 'You have broken everything and now I hate you.';
});
}
Adding a customized section to the debug screen:
<?php
use Kuria\Error\Screen\WebErrorScreen;
use Kuria\Error\Screen\WebErrorScreenEvents;
$errorScreen = $errorHandler->getErrorScreen();
if ($errorHandler->isDebugEnabled() && $errorScreen instanceof WebErrorScreen) {
// add custom CSS
$errorScreen->on(WebErrorScreenEvents::CSS, function () {
echo '#custom-group {color: #f60000;}';
});
// add custom HTML
$errorScreen->on(WebErrorScreenEvents::RENDER_DEBUG, function (array $view) {
$view['extras'] .= <<<HTML
<div id="custom-group" class="group">
<div class="section">
Example of a custom section
</div>
</div>
HTML;
});
}