mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 19:58:22 +08:00
174 lines
4.9 KiB
Markdown
174 lines
4.9 KiB
Markdown
# Excepiton Handler
|
|
|
|
In `Hyperf`, all the business code excute on `Worker Process`. In this case, once any request has an exception that has not been caught, the corresponding `Worker Process` will be interrupted and exited, which is unacceptable for the service. Catch exceptions and output reasonable error content is also more friendly to the client. We can define different `ExceptionHandlers` for each `server`, and once there are exceptions that are not caught in the process, they will be passed to the registered `ExceptionHandler` for processing.
|
|
|
|
## Customize an Exception Handling
|
|
|
|
### Register Exception Handler
|
|
|
|
Currently, it only supports the registration of `ExceptionHandler` in the form of a configuration file. The configuration file is located in `config/autoload/exceptions.php`. Configure your custom exception handler under the corresponding `server`:
|
|
|
|
```php
|
|
<?php
|
|
// config/autoload/exceptions.php
|
|
return [
|
|
'handler' => [
|
|
// The http here corresponds to the name value corresponding to the server in config/autoload/server.php
|
|
'http' => [
|
|
// The registration of the exception handler has done by configuring the complete class namespace address here
|
|
\App\Exception\Handler\FooExceptionHandler::class,
|
|
],
|
|
],
|
|
];
|
|
```
|
|
|
|
> The order of each exception handler configuration array determines the order in which exceptions are passed between handlers.
|
|
|
|
### Define Exception Handler
|
|
|
|
We can define a `class (Class)` anywhere and inherit the abstract class `Hyperf\ExceptionHandler\ExceptionHandler` and implement the abstract methods in it. As shown below:
|
|
|
|
```php
|
|
<?php
|
|
namespace App\Exception\Handler;
|
|
|
|
use Hyperf\ExceptionHandler\ExceptionHandler;
|
|
use Hyperf\HttpMessage\Stream\SwooleStream;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use App\Exception\FooException;
|
|
use Throwable;
|
|
|
|
class FooExceptionHandler extends ExceptionHandler
|
|
{
|
|
public function handle(Throwable $throwable, ResponseInterface $response)
|
|
{
|
|
// Determine that the caught exception is the wanted exception
|
|
if ($throwable instanceof FooException) {
|
|
// Formatted output
|
|
$data = json_encode([
|
|
'code' => $throwable->getCode(),
|
|
'message' => $throwable->getMessage(),
|
|
], JSON_UNESCAPED_UNICODE);
|
|
|
|
// Prevent bubbling
|
|
$this->stopPropagation();
|
|
return $response->withStatus(500)->withBody(new SwooleStream($data));
|
|
}
|
|
|
|
// Hand over to the next exception handler
|
|
return $response;
|
|
|
|
// Or directly shield the exception without processing
|
|
}
|
|
|
|
/**
|
|
* Determine whether the exception handler needs to handle the exception or not
|
|
*/
|
|
public function isValid(Throwable $throwable): bool
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Define Exception Class
|
|
|
|
```php
|
|
<?php
|
|
namespace App\Exception;
|
|
|
|
use App\Constants\ErrorCode;
|
|
use Hyperf\Server\Exception\ServerException;
|
|
use Throwable;
|
|
|
|
class FooException extends ServerException
|
|
{
|
|
}
|
|
```
|
|
|
|
### Trigger Exception
|
|
|
|
```php
|
|
|
|
namespace App\Controller;
|
|
|
|
use App\Exception\FooException;
|
|
|
|
class IndexController extends AbstractController
|
|
{
|
|
public function index()
|
|
{
|
|
throw new FooException('Foo Exception...', 800);
|
|
}
|
|
}
|
|
|
|
```
|
|
In the example above, we assume that `FooException` is a thrown exception, and exception handlers are configured. When an uncaught exception has been thrown, it will be passed through the handler registration order. Imagine the processing as a pipe, the exception will not be passed once there are some handler calls `$this->stopPropagation()`. The default handler of Hyperf will be the last one to catch exceptions if there is no other handler to catch such exceptions.
|
|
|
|
## Integrated Whoops
|
|
|
|
The framework provides Whoops integration.
|
|
|
|
Install Whoops first
|
|
```php
|
|
composer require --dev filp/whoops
|
|
```
|
|
|
|
Then configure the special exception handler for Whoops.
|
|
|
|
```php
|
|
// config/autoload/exceptions.php
|
|
return [
|
|
'handler' => [
|
|
'http' => [
|
|
\Hyperf\ExceptionHandler\Handler\WhoopsExceptionHandler::class,
|
|
],
|
|
],
|
|
];
|
|
```
|
|
|
|
As shown in the image:
|
|
|
|
![whoops](/imgs/whoops.png)
|
|
|
|
|
|
## Error Listener
|
|
|
|
The framework provides the `error_reporting()` error level listener `Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler`.
|
|
|
|
### Configuration
|
|
|
|
Add a listener in `config/autoload/listeners.php`
|
|
|
|
```php
|
|
<?php
|
|
return [
|
|
\Hyperf\ExceptionHandler\Listener\ErrorExceptionHandler::class
|
|
];
|
|
```
|
|
|
|
When a code similar to the following appears, `\ErrorException` will be thrown
|
|
|
|
```php
|
|
<?php
|
|
try {
|
|
$a = [];
|
|
var_dump($a[1]);
|
|
} catch (\Throwable $throwable) {
|
|
var_dump(get_class($throwable), $throwable->getMessage());
|
|
}
|
|
|
|
// string(14) "ErrorException"
|
|
// string(19) "Undefined offset: 1"
|
|
```
|
|
|
|
If no listener is configured, no exception will be thrown.
|
|
|
|
```
|
|
PHP Notice: Undefined offset: 1 in IndexController.php on line 24
|
|
|
|
Notice: Undefined offset: 1 in IndexController.php on line 24
|
|
NULL
|
|
```
|
|
|