Hyperf 开发模式下需确保异常冒泡至框架处理器并正确响应记录,关键在于配置异常处理器顺序、禁用静默捕获、启用 stdout 日志及终端直连输出。

Hyperf 开发模式下要让未捕获的运行异常清晰输出,关键不是“打开开关”,而是确保异常能真正冒泡到框架的异常处理器,并被正确响应和记录。默认配置下,部分异常可能被静默吞掉、被错误拦截,或因协程环境导致日志丢失。
确认异常处理器已注册且顺序合理
检查 config/autoload/exceptions.php 中 HTTP 类型的异常处理器列表,必须包含至少一个有效处理器,且顺序符合预期:
- 内置的 HttpExceptionHandler 应排在自定义处理器(如
AppExceptionHandler)之前,避免它把 404、405 等标准异常误转为 500; - 自定义处理器的
isValid()方法不能无差别返回true,否则会拦截所有异常,包括队列、定时任务等非 HTTP 场景的异常; - 若仅用于开发调试,可临时让
isValid()对Throwable返回true,但上线前务必收紧条件。
关闭生产级静默行为
开发阶段应禁用可能掩盖问题的配置:
- 在 config/autoload/async_queue.php 中,确保
'handle_timeout'不设过短(如 1 秒),避免协程被硬杀而中断异常抛出流程; - 检查全局中间件或 AOP 切面,确认没有在
try/catch中空捕获并吞掉异常; - Job 类的
handle()方法里禁止出现catch (\Exception $e) { }这类静默块——它会让框架认为任务成功,既不重试也不记日志。
启用实时日志与终端直出
让异常不仅写日志,还能在终端直观看到:
- 确保 config/autoload/logger.php 中
'default'日志驱动为stdout或daily,且级别设为'debug'; - 在
App\Exception\Handler\AppExceptionHandler的handle()方法中,调用logger()->error()记录完整堆栈,并确保$this->stopPropagation()被调用以终止传递; - 启动服务时使用
php bin/hyperf.php start --watch,配合 watcher 实时刷新,异常会直接打印在控制台,含文件行号和上下文。
验证是否生效的小技巧
写一段测试代码主动触发异常,观察输出位置和内容:
- 在控制器中加
throw new \RuntimeException('dev test');,看 HTTP 响应体是否返回结构化错误,同时终端是否有堆栈; - 在 Job 的
handle()中抛异常,检查 Redis 的async-queue:failed是否有记录,以及storage/logs/下是否有对应日志; - 若只有日志没终端输出,说明异常被某层提前捕获;若连日志都没有,大概率是
handle_timeout杀协程或序列化失败导致任务根本没执行到handle()。


















