Hyperf自定义异常需三者协同:定义继承RuntimeException的业务异常类(含code/message)、编写精准匹配并调用stopPropagation()的异常处理器、按优先级在exceptions.php中注册;否则默认返回500或空响应。

Hyperf 自定义异常类输出接口报错详情,核心在于异常类 + 异常处理器 + 响应格式三者协同,不能只抛一个异常就指望自动返回结构化错误信息。默认情况下,Hyperf 会把未捕获异常转为 500 页面或空响应,必须主动干预。
1. 定义业务异常类(带 code 和 message)
继承 RuntimeException 即可,无需特殊接口。重点是构造时传入业务码和提示,方便后续提取:
- code 用于 JSON body 中的业务错误码(如 1001、2002),不是 HTTP 状态码
- message 是面向前端或日志的简明提示,比如“用户不存在”
- 不要重写
getCode()方法——它默认返回构造参数,够用
示例:/app/Exception/UserNotFoundException.php
<?php
namespace App\Exception;
class UserNotFoundException extends \RuntimeException
{
}
// 使用:throw new UserNotFoundException('用户不存在', 1001);
2. 编写专用异常处理器(精准匹配 + 终止传播)
处理器必须实现 isValid() 严格判断类型,并在 handle() 中手动设置状态码、构造 JSON、调用 stopPropagation():
- HTTP status 固定用 4xx/5xx(如 404),别把业务码 1001 当 status 传给
withStatus() - JSON body 包含
code(业务码)、message(提示)、trace_id(可选,便于查日志) - 漏掉
$this->stopPropagation()会导致异常继续传递,可能被后续兜底处理器覆盖成 500
示例:/app/Exception/Handler/UserNotFoundHandler.php
<?php
namespace App\Exception\Handler;
use App\Exception\UserNotFoundException;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Throwable;
class UserNotFoundHandler extends ExceptionHandler
{
public function handle(Throwable $throwable, ResponseInterface $response)
{
$this->stopPropagation();
$data = json_encode([
'code' => $throwable->getCode(),
'message' => $throwable->getMessage(),
'trace_id' => $this->container->get(\Hyperf\Tracer\Tracer::class)->getTraceId() ?? '',
], JSON_UNESCAPED_UNICODE);
return $response->withStatus(404)->withBody(new SwooleStream($data));
}
public function isValid(Throwable $throwable): bool
{
return $throwable instanceof UserNotFoundException;
}
}
3. 注册到配置并注意顺序
在 config/autoload/exceptions.php 的 http 数组中注册,且必须放在 HttpExceptionHandler 之后:
- 如果放太前,连 404、405 这类框架原生异常也会被你拦截,导致前端收不到正确 status
- 数组顺序 = 匹配优先级,越靠前越先试
isValid()
正确配置示例:
return [
'handler' => [
'http' => [
// 框架内置兜底,处理所有 HttpException 子类(含 404/405)
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
// 自定义处理器,仅处理特定业务异常
App\Exception\Handler\UserNotFoundHandler::class,
App\Exception\Handler\AppExceptionHandler::class,
],
],
];
4. 触发验证与调试技巧
在控制器中直接抛出测试,用 curl 或 Postman 请求,观察响应:
- 响应 status 应为 404,body 是标准 JSON,含
code和message - 查看
runtime/logs/hyperf.log,确认是否只有一条该异常的日志(若重复出现,说明stopPropagation()没生效) - 开启调试模式(
SWOOLE_LOG_LEVEL=5)可看到异常传递链路
不复杂但容易忽略。


















