webman异常处理需手动配置config/exception.php并实现render()和report(),兜底处理器键名必须为'',类须实现exceptionhandlerinterface,render()须设json头并返回response实例,业务异常需显式判断并区分告警。

Webman 默认不返回 JSON 异常,也不自动记录完整错误上下文——必须手动配置 config/exception.php 并实现 render() 和 report(),否则线上出错只能靠翻 workerman.log 猜。
config/exception.php 必须用空字符串键注册处理器
Webman 只认 '' 这个键名作为兜底异常处理器,写成 'default'、'app' 或留着注释行 // '' => ... 都无效。框架直接跳过,退回到原始 HTML 错误页。
- 删掉配置文件里所有带
//的注册行,避免干扰 - 路径必须能被 PSR-4 自动加载,推荐放
app/exception/ExceptionHandler.php - 类必须实现
Webman\Exception\ExceptionHandlerInterface,否则启动时报致命错误 - 示例正确写法:
return ['' => app\exception\ExceptionHandler::class];
render() 方法必须手动设 header 并返回 Response 实例
即使你 return ['code' => 500, 'msg' => 'xxx'],Webman 也不会自动加 Content-Type: application/json,前端 fetch().json() 会直接抛错。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 开头必须写
header('Content-Type: application/json; charset=utf-8'); - 返回值必须是
support\Response实例,不能是数组或字符串 - 最稳妥写法:
return response()->json(['code' => 500, 'msg' => $e->getMessage(), 'trace_id' => $request->header('x-trace-id', uniqid('tr_'))]); - 若手动
json_encode(),务必加JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,否则中文乱码或静默失败
区分 BusinessException 和 Throwable 才能精准响应与告警
support\exception\BusinessException 是 Webman 内置的语义化异常,抛出时自动带 code 字段、不走完整堆栈;但一旦你重写了 render(),这个行为就被覆盖,必须手动识别。
- 用
$e instanceof support\exception\BusinessException判断业务异常,取$e->getCode()作响应code - 普通
Throwable(如数据库断连、内存溢出)统一返回500,且生产环境绝不能透出$e->getTraceAsString() - 业务异常不该触发告警,系统异常才需要立刻通知;告警逻辑应放在
report()里,而非render() - 别在中间件里
try/catch全部逻辑——会掩盖真实错误位置,ExceptionHandler是唯一正统入口
日志没写进 webman.log?先查这三处
线上异常发生,runtime/logs/webman.log 却空空如也,问题大概率不在日志内容本身,而在链路中断点。
-
config/exception.php被误删或返回空数组,导致默认处理器没加载,异常直接透出给 Worker,而 Worker 日志走的是workerman.log -
config/log.php中'default'键名拼错(比如写成'defalut'),框架 fallback 到无 handler 状态 - 自定义异常类(如
app\exception\BusinessException)抛出后,config/exception.php里没注册对应处理器,它就掉进兜底处理器——但兜底处理器在APP_DEBUG = false时默认不打堆栈到日志 - 验证方法:在路由闭包里写
throw new \Exception('test');,看webman.log是否出现带 trace 的条目
真正难的不是写一个能返回 JSON 的 render(),而是让 report() 在任意异常下都稳定落库、打标、透传 trace_id,并且不被中间件顺序或 debug 开关意外截断——这些细节不验一遍,线上排障时永远慢半拍。









