hyperf异常必须由exceptionhandler捕获,server name需与exceptions.php中handler键名严格一致;handle()须手动设status并调用stoppropagation();validationexception需返回完整errors字段;注意协程上下文绑定日志与响应。

Hyperf控制器异常必须由 ExceptionHandler 捕获,不能靠中间件或控制器内 try/catch 兜底——因为未捕获的异常会直接中断协程,导致 Worker 进程退出,影响其他请求。
确认 server name 与 exceptions.php 中 handler 键名严格一致
Hyperf 按 HTTP Server 的 name 字段路由异常处理器,不匹配就完全不生效。
- 运行
php bin/hyperf.php start,看启动日志中类似[INFO] Server started: http://0.0.0.0:9501前面标注的name(如http、api) - 打开
config/autoload/server.php,找到对应 HTTP server 块中的'name' => 'xxx' - 打开
config/autoload/exceptions.php,确保'handler' => ['xxx' => [...]]的键名与上一步一模一样,大小写、空格都不能差 - 若写成
'http'但实际是'api',你的AppExceptionHandler根本不会被调用,请求会走框架默认兜底,返回空白或 500
handle() 方法里必须显式设置 status 并调用 stopPropagation()
Hyperf 不会自动把异常 getCode() 映射为 HTTP 状态码,也不会自动终止异常传递链。
-
$response->withStatus(422)或withStatus(500)必须手动调用,否则响应状态始终是默认的 500 -
$this->stopPropagation()必须在handle()中执行,否则异常继续往下传,可能被HttpExceptionHandler拦截,导致你写的 JSON 结构失效 - 只写
return $response->json([...])不够,status和传播控制缺一不可 - 验证方式:在控制器里
throw new \RuntimeException('test'),看响应体是否含你定义的字段,同时终端是否有对应日志
ValidationException 要完整返回 errors 字段
自定义 ValidationExceptionHandler 时,容易只取 first() 或漏掉 messages(),导致前端收不到具体错误字段。
- 不要用
$throwable->validator->errors()->first()—— 它只返回第一个错误字符串 - 应调用
$throwable->validator->errors()->messages()获取关联数组,再组装为标准结构:['message' => ..., 'errors' => [...]] - 确认
storage/languages/zh_CN/validation.php存在且 key 名匹配规则(如'required' => ':attribute 为必填项'),否则errors为空 - 检查
config/autoload/middlewares.php的http数组是否包含Hyperf\Validation\Middleware\ValidationMiddleware::class
协程上下文丢失会导致日志和响应错乱
在 Swoole 协程环境下,logger() 和 $response 若没绑定当前协程上下文,会出现日志混杂、响应体缺失、状态码覆盖等问题。
- 在
handle()中记录日志时,显式传入协程 ID:logger()->error($e->getMessage(), ['cid' => \Swoole\Coroutine::getCid()]) - 避免在
handle()外部提前catch异常(比如在中间件或 AOP 切面里静默吞掉),否则异常根本进不了ExceptionHandler - Job 类的
handle()方法里禁止出现catch (\Exception $e) { }—— 它会让框架认为任务成功,既不重试也不记日志 - 开发阶段建议加
--watch启动:php bin/hyperf.php start --watch,异常堆栈会直出终端,带文件行号和上下文











