Webman默认异常响应非纯JSON,需显式配置自定义异常处理器并实现render方法:手动设置header、返回Response实例、按debug状态区分响应格式,且必须注册到config/exception.php空键下。

Webman 默认异常响应不是纯 JSON,必须显式配置自定义异常处理器才能稳定返回结构化 JSON。直接改 config/exception.php 指向自定义类只是第一步,render 方法里不手动构造 JSON、不设 header、不处理 debug 状态,前端照样收到 HTML 错误页或裸文本。
配置 config/exception.php 指向自定义处理器类
Webman 不会自动加载你写的 ExceptionHandler,必须在 config/exception.php 显式注册路径。默认配置里注释掉的那行不能留着:
- 删掉
// '' => support\exception\Handler::class,这类注释行,避免误读 - 确保键名是空字符串
'',不是'default'或其他字符串,否则无效 - 类路径必须能被自动加载,推荐用 PSR-4 规范放在
app/exception/下,命名如ExceptionHandler - 类必须实现
Webman\Exception\ExceptionHandlerInterface,否则启动时报错
render() 方法必须手动输出 JSON 并设置 header
Webman 的 render() 方法不自动加 Content-Type: application/json,也不自动调用 json_encode()。常见错误是只 return 一个数组,结果浏览器当成 HTML 渲染:
- 开头必须写
header('Content-Type: application/json; charset=utf-8'); - 返回值必须是
support\Response实例,不能直接return ['code' => 500, 'msg' => $e->getMessage()] - 用
response()->json()最稳妥,它内部已处理 header 和编码;若手动json_encode(),记得加JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR - debug 为 true 时,
$e->getTraceAsString()可能含敏感路径,生产环境务必过滤或禁用
区分 BusinessException 和普通 Exception 的响应逻辑
Webman 对 support\exception\BusinessException 有特殊支持:抛出时自动带 code 字段,且不走完整异常栈。但如果你重写了 render(),这个行为会被覆盖,需手动识别:
立即学习“PHP免费学习笔记(深入)”;
- 用
$e instanceof support\exception\BusinessException判断业务异常 - 取
$e->getCode()作为响应 code,而非硬写500 - 普通 Exception 建议统一返回
500,BusinessException 返回400、401等语义化码 - 不要在
render()里 try-catchjson_encode()失败,它本身已 throw,应让框架捕获并 fallback 到 raw text
避免 response 输出前被其他中间件或钩子污染
Webman 中间件顺序影响最终响应。如果某个中间件(比如日志、CORS)在异常处理器之后执行,可能篡改 header 或提前输出内容,导致 JSON 解析失败:
- 确认
config/middleware.php中异常处理中间件(如有)位置靠前,或干脆不用中间件做异常响应 - 禁止在
render()外部 echo/print 任何内容,包括空格、BOM、调试语句 - 检查
config/app.php的debug值是否与预期一致,app.debug = false时才触发简略 JSON,否则返回带 trace 的 HTML 页面 - 用 curl 测试:
curl -H "Accept: application/json" http://127.0.0.1:8787/test,观察原始响应体,排除浏览器缓存干扰
最易忽略的是 app.debug 开关和 Accept 请求头的组合效果——Webman 只有在请求头明确声明需要 JSON 且 app.debug = false 时,才会对非 Business 异常返回精简 JSON;否则要么返回 HTML 调试页,要么 fallback 到文本格式。这点不验证清楚,所有配置都白搭。



















