12、Hyperf 3 快速使用 - 自定义异常处理
hi,我是温新,一名 PHPer
Hypref 版本:Hyperf 3.0
学习目标:掌握异常的处理
本篇文章将学习两种自定义异常类的使用方法,先开开始吧。
异常在 API 开发中经常使用到,一定要掌握。
方式一:自定义异常类
第一步:定义异常处理器
<?php
// App\Exception\Handler\ApiExceptionHandler.php
namespace App\Exception\Handler;
use App\Exception\ApiException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Throwable;
class ApiExceptionHandler extends ExceptionHandler
{
public function handle(Throwable $throwable, ResponseInterface $response)
{
// 判断被捕获到的异常是希望被捕获的异常
if ($throwable instanceof ApiException) {
// 格式化输出
$data = json_encode([
'code' => $throwable->getCode(),
'message' => $throwable->getMessage(),
], JSON_UNESCAPED_UNICODE);
// 阻止异常冒泡
$this->stopPropagation();
return $response->withStatus(500)->withBody(new SwooleStream($data));
}
// 交给下一个异常处理器
return $response;
}
// 判断该异常类是否要对该异常进行处理
public function isValid(Throwable $throwable): bool
{
return true;
}
}
第二步:定义异常类
<?php
// App\Exception\ApiException.php
namespace App\Exception;
use Hyperf\Server\Exception\ServerException;
class ApiException extends ServerException
{
}
第三步:配置文件中注册异常处理器
<?php
// config/autoload/exceptions.php
declare(strict_types=1);
return [
'handler' => [
'http' => [
// 省略
\App\Exception\Handler\ApiExceptionHandler::class,
],
],
];
第四步:触发异常类
<?php
// App\Controller\IndexController.php
use App\Exception\ApiException;
public function index()
{
throw new ApiException('api error', 500);
}
第五步:测试异常类
$ curl http://localhost:9501/
{"code":500,"message":"api error"}
方式二:通过容器绑定异常类
第一步:创建异常类
<?php
namespace App\Exception;
use Hyperf\Server\Exception\ServerException;
class NewApiException extends ServerException
{
}
第二步:创建统一响应类
<?php
declare(strict_types=1);
namespace App\Components;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Container\ContainerInterface;
class Response
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var ResponseInterface
*/
protected $response;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->response = $container->get(ResponseInterface::class);
}
public function success($data = [])
{
return $this->response->json([
'code' => 0,
'data' => $data,
]);
}
public function fail($code, $message = '')
{
return $this->response->json([
'code' => $code,
'message' => $message,
]);
}
}
第三步:修改 AbstractController
抽象控制器
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Components\Response;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Container\ContainerInterface;
abstract class AbstractController
{
#[Inject]
protected ContainerInterface $container;
#[Inject]
protected RequestInterface $request;
// 此处改为统一响应
#[Inject]
protected Response $response;
}
第四步:修改 AppExceptionHandler.php
类
<?php
declare(strict_types=1);
namespace App\Exception\Handler;
use App\Components\Response;
use App\Exceptions\NewApiException;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Throwable;
class AppExceptionHandler extends ExceptionHandler
{
public function __construct(protected StdoutLoggerInterface $logger, protected Response $response)
{
}
public function handle(Throwable $throwable, ResponseInterface $response)
{
// 处理业务异常
if ($throwable instanceof NewApiException) {
return $this->response->fail(101, $throwable->getMessage());
}
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->logger->error($throwable->getTraceAsString());
return $response->withHeader('Server', 'Hyperf')->withStatus(500)->withBody(new SwooleStream('Internal Server Error.'));
}
public function isValid(Throwable $throwable): bool
{
return true;
}
}
第五步:响应测试
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Exception\ApiException;
use App\Exception\FooException;
use App\Exceptions\NewApiException;
class IndexController extends AbstractController
{
public function index()
{
throw new FooException('new api error', 800);
}
}
请登录后再评论