hyperf异常处理需按环境区分策略:开发环境输出完整堆栈和请求参数,生产环境仅返回简洁code+message;http状态码与业务code严格分离;响应体需结构化并注入trace_id等上下文;注册handler后须检查配置顺序、isvalid返回值及stoppropagation调用。

Hyperf 的异常格式化输出不是默认就友好的,尤其在调试阶段,原始堆栈或空白响应会拖慢排查效率。关键在于让异常既保留开发所需上下文,又不泄露敏感信息,还要适配不同环境。
明确区分开发与生产环境的输出策略
开发时需要完整堆栈、文件行号、请求参数;生产环境则必须隐藏堆栈,只返回简洁 code + message。Hyperf 本身不自动切换,需手动控制:
- 在 config/autoload/exceptions.php 中,可基于
env('APP_ENV') === 'dev'动态注册不同的 handler - 开发用的 handler 可调用
$throwable->getTraceAsString()并嵌入响应体;生产用的 handler 则只取$throwable->getMessage()和预设 code - 避免在生产环境直接输出
var_dump或print_r,它们可能破坏 JSON 结构或触发协程异常
统一结构化响应体,避免 status 与业务 code 混淆
HTTP 状态码(如 422、500)和业务错误码(如 1001、2003)应严格分离:
- HTTP status 由
$response->withStatus()显式设置,仅限标准语义值(2xx/4xx/5xx) - 业务 code 放在 JSON body 的
code字段,例如{"code": 1002, "message": "参数缺失", "data": {}} - 不要把
ValidationException::getCode()直接当 HTTP status 用——它默认是 0,且语义上属于业务层
捕获并注入请求上下文,辅助快速定位
单看异常本身往往不够,需附带当前请求的关键信息:
- 从容器中获取
RequestInterface,提取uri()、method()、all()(注意过滤 password/token 类字段) - 使用
ApplicationContext::getContainer()->get(LoggerInterface::class)记录结构化日志,包含 trace_id、request_id、IP、URI - 可在响应体中加入
trace_id字段,方便日志平台关联检索
验证 handler 是否生效的三步检查法
写完 handler 常见“没反应”,别急着改逻辑,先确认注册链路是否通畅:
- 查 config/autoload/exceptions.php 中该 handler 是否在
'http'数组里,且顺序合理(自定义类应在HttpExceptionHandler之后) - 确认
isValid()方法返回true仅针对目标异常类型,避免return true导致误吞其他异常 - 务必调用
$this->stopPropagation(),否则异常会继续传递,可能被后续 handler 覆盖或导致重复记录











