3.5 异常处理
在 Hyperf
里,业务代码都运行在 Worker 进程
上,也就意味着一旦任意一个请求的业务存在没有捕获处理的异常的话,都会导致对应的 Worker 进程
被中断退出,这对服务而言也是不能接受的,捕获异常并输出合理的报错内容给客户端也是更加友好的。
我们可以通过对各个 server
定义不同的 异常处理器(ExceptionHandler)
,一旦业务流程存在没有捕获的异常,都会被传递到已注册的 异常处理器(ExceptionHandler)
去处理。
1. 创建处理某个异常的类
touch app/Exception/Handler/ResourceExceptionHandler.php
<?php
namespace AppExceptionHandler;
use HyperfContractStdoutLoggerInterface;
use HyperfDiAnnotationInject;
use HyperfExceptionHandlerExceptionHandler;
use HyperfHttpMessageStreamSwooleStream;
use PsrHttpMessageResponseInterface;
use Throwable;
class ResourceExceptionHandler extends ExceptionHandler
{
/**
* @var StdoutLoggerInterface
*/
protected $logger;
/**
* @Inject()
* @var HyperfHttpServerContractResponseInterface
*/
protected $response;
public function __construct(StdoutLoggerInterface $logger)
{
$this->logger = $logger;
}
public function handle(Throwable $throwable, ResponseInterface $response)
{
// 不再往下传递异常错误
$this->stopPropagation();
// 将错误的信息返回出去
return $this->response->json([
'error' => 500,
'data' => []
]);
}
/**
* 确定当前的异常处理程序是否应该处理异常。
*/
public function isValid(Throwable $throwable): bool
{
return $throwable instanceof AppExceptionResourceException;
}
}
2. 创建异常类
touch app/Exception/ResourceException.php
<?php
namespace AppException;
class ResourceException extends RuntimeException
{
}
3. 定义异常:在config/autoload/exceptions.php中定义
<?php
return [
'handler' => [
'http' => [
HyperfHttpServerExceptionHandlerHttpExceptionHandler::class,
AppExceptionHandlerAppExceptionHandler::class,
// 注册之前定义好的错误处理类
AppExceptionHandlerResourceExceptionHandler::class
],
],
];
4. 使用
<?php
namespace AppController;
use AppExceptionResourceException;
use HyperfHttpServerAnnotationAutoController;
use HyperfHttpServerAnnotationMiddleware;
use HyperfHttpServerAnnotationMiddlewares;
/**
* @AutoController()
*/
class IndexController extends AbstractController
{
public function index()
{
throw new ResourceException();
}
}