webman需手动配置异常处理器并重写render()方法返回json响应,否则前端可能收到html错误页;必须用空字符串键注册、实现接口、设content-type头、返回response实例,并区分业务异常与普通异常处理逻辑。

Webman 默认不返回标准 JSON 异常,必须手动配置异常处理器并重写 render() 方法,否则前端收到的可能是 HTML 错误页、裸文本或状态码错乱的响应。
config/exception.php 配置必须用空字符串键
Webman 只识别 ''(空字符串)作为默认异常处理器的注册键,写成 'default'、'webman' 或留着注释行 // '' => ... 都无效:
- 删掉所有注释掉的配置行,避免干扰
- 确保路径能被自动加载,推荐放在
app/exception/ExceptionHandler.php - 类必须实现
Webman\Exception\ExceptionHandlerInterface接口,否则启动时报致命错误 - 路径写法示例:
'' => app\exception\ExceptionHandler::class
render() 方法里必须手动设 header 并返回 Response 实例
render() 不会自动设置 Content-Type: application/json,也不自动调用 json_encode()。常见错误是直接 return ['code' => 500],结果浏览器当 HTML 渲染:
- 开头必须加
header('Content-Type: application/json; charset=utf-8'); - 返回值必须是
support\Response实例,不能是数组或字符串 - 最稳妥写法:
return response()->json(['code' => 500, 'msg' => $e->getMessage()])->withStatus(500); - 若手动
json_encode(),务必加JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR -
app.debug = true时,$e->getTraceAsString()含敏感路径,生产环境需过滤或跳过
区分 BusinessException 和普通 Exception 的响应逻辑
Webman 对 support\exception\BusinessException 有内置支持(如自动携带 code 字段),但自定义 render() 会覆盖该行为,必须手动识别:
- 用
$e instanceof support\exception\BusinessException判断业务异常 - 取
$e->getCode()作为响应code字段,不要硬写500 - 普通
Exception建议统一返回code: 500,HTTP 状态码也设为500 - 业务异常建议用
400、401等语义化 HTTP 状态码,但注意:前端fetch().json()仍会执行,只要 body 是合法 JSON 就可解析
统一响应结构别靠异常处理器兜底
异常处理器只管“出错怎么报”,不该承担“正常返回长什么样”的职责。所有控制器应主动走统一响应封装,比如 Result::Success():
- 不要在
try/catch里手写echo json_encode(...),会漏设 header、状态码、编码 - 所有分支(包括
catch)都调用同一工具方法,如Result::ErrorCode(4001, '参数缺失') -
json()默认不格式化,调试时可临时加JSON_PRETTY_PRINT,但绝不能全局开启——它增大体积、拖慢吞吐 - 中间件顺序影响最终响应,比如日志中间件或限流中间件可能提前终止或修改响应,要确认它们没覆盖你设的 status 或 body
最容易被忽略的是:异常处理器生效的前提是请求真正“抛出了未捕获异常”。如果控制器里写了 try/catch 却没重新抛出,或者用了 http_response_code(500) + echo,那你的 render() 根本不会触发。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











