133 lines
5 KiB
Markdown
133 lines
5 KiB
Markdown
[<< previous](02-composer.md) | [next >>](04-development-helpers.md)
|
|
|
|
### Error Handler
|
|
|
|
An error handler allows you to customize what happens if your code results in an error.
|
|
|
|
It is important to clearly define how your project should behave when it encounters an error, and especially where it
|
|
should output the information about an error.
|
|
|
|
We want to mainly focus on Exceptions, which are an encapsulation of errors in php. We also have "normal" errors, but
|
|
most of them are currently being changed currently into Exceptions.
|
|
|
|
```php
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Lubiana\NoFramework;
|
|
|
|
use ErrorException;
|
|
use Throwable;
|
|
|
|
set_exception_handler(function (Throwable $t) {
|
|
$errorType = match($t->getCode()) {
|
|
E_ERROR, E_USER_ERROR => 'Fatal Error',
|
|
E_WARNING, E_USER_WARNING => 'Warning',
|
|
E_NOTICE, E_USER_NOTICE => 'Notice',
|
|
default => 'Unknown Error'
|
|
};
|
|
|
|
echo <<<HTML
|
|
<h1>{$errorType}</h1>
|
|
<p>{$t->getMessage()}</p>
|
|
<pre>{$t->getTraceAsString()}</pre>
|
|
HTML;
|
|
});
|
|
|
|
set_error_handler(
|
|
function (int $errno, string $errstr, string $errfile, int $errline) {
|
|
throw new ErrorException(
|
|
message: $errstr,
|
|
code: $errno,
|
|
severity: $errno,
|
|
filename: $errfile,
|
|
line: $errline
|
|
);
|
|
}
|
|
);
|
|
|
|
echo 'Hello world!';
|
|
```
|
|
|
|
You can then replace `echo 'Hello world!';` with `trigger_error('This is a test error');`
|
|
or `throw new Exception('This is a test exception');` and open it in your browser to see if the error handling works.
|
|
|
|
|
|
During development there are some other nice features to add. For example a quick link to open your Editor on the file the Error occured. So the first package
|
|
for your application will take care of that.
|
|
|
|
I like [filp/whoops](https://github.com/filp/whoops), so I will show how you can install that package for your project.
|
|
If you prefer another package, feel free to install that one. This is the beauty of programming without a framework,
|
|
you have total control over your project.
|
|
|
|
Some alternatives would be: [PHP-Error](https://github.com/JosephLenton/PHP-Error) or [Tracy](https://tracy.nette.org/en/)
|
|
|
|
To install that package into your project simply type `composer require filp/whoops` into your terminal at the project root,
|
|
now composer automatically looks for a version of that package compatible with the rest of your project and your php
|
|
version.
|
|
|
|
But you can't use it yet. PHP won't know where to find the files for the classes. For this you will need an autoloader,
|
|
ideally a [PSR-4](http://www.php-fig.org/psr/psr-4/) autoloader. Composer already takes care of this for you, so you
|
|
only have to add a `require __DIR__ . '/../vendor/autoload.php';` to your `Bootstrap.php`.
|
|
|
|
**Important:** Never show any errors in your production environment. A stack trace or even just a simple error message
|
|
can help someone to gain access to your system. Always show a user-friendly error page instead and send an email to
|
|
yourself, write to a log or something similar. So only you can see the errors in the production environment.
|
|
|
|
For development that does not make sense, though -- you want a nice error page. The solution is to have an environment
|
|
switch in your code. We use the getenv() function here to check the environment and define the 'dev' env as standard in
|
|
case no environment has been set.
|
|
|
|
Then after the error handler registration, throw an `Exception` to test if everything is working correctly.
|
|
Your `Bootstrap.php` should now look similar to this:
|
|
|
|
```php
|
|
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Lubiana\NoFramework;
|
|
|
|
use Throwable;
|
|
use Whoops\Handler\CallbackHandler;
|
|
use Whoops\Handler\PrettyPageHandler;
|
|
use Whoops\Run;
|
|
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
$environment = getenv('APP_ENV') ?: 'dev';
|
|
|
|
$whoops = new Run;
|
|
$whoops->pushHandler(
|
|
new CallbackHandler(
|
|
function (Throwable $e) use ($environment) {
|
|
if ($environment !== 'dev') {
|
|
http_response_code(500);
|
|
echo 'Whoops';
|
|
}
|
|
error_log(<<<TXT
|
|
Error: {$e->getMessage()}
|
|
{$e->getTraceAsString()}
|
|
TXT
|
|
);
|
|
}
|
|
)
|
|
);
|
|
|
|
if ($environment === 'dev') {
|
|
$whoops->pushHandler(new PrettyPageHandler);
|
|
}
|
|
$whoops->register();
|
|
|
|
throw new \Exception('Hello world');
|
|
|
|
```
|
|
|
|
You should now see a error page with the line highlighted where you throw the exception. If not, go back and debug until
|
|
you get it working. Now would also be a good time for another commit.
|
|
|
|
**Side-note:** Here we use `getenv()` to read a Variable from the Environment and fallback to using 'dev' if it is not set. That is a bad default, and in a production app you should always default to the strictest mode.
|
|
There are also good libraries that help with managing that in a better fashion. You can take a look at [phpdotenv](https://github.com/vlucas/phpdotenv) or [symfony/dotenv](https://github.com/symfony/dotenv) and maybe implement them. This tutorial however skips this step.
|
|
|
|
[<< previous](02-composer.md) | [next >>](04-development-helpers.md)
|