ThinkPHP接口返回JSON必须统一格式,核心是所有响应(含异常)均采用{"code":int,"msg":str,"data":mixed}结构。需在BaseController封装success/error方法、在Handler中统一处理异常、用中间件兜底封装响应,并确保UTF-8无BOM、无额外输出、正确设置跨域头及解析JSON请求体。

ThinkPHP 接口返回 JSON 时,统一格式不是“可选优化”,而是前后端协作的底线要求。核心目标是:所有接口无论成功或失败,都返回结构一致、字段语义明确、状态码可编程的 JSON,例如 {"code":200,"msg":"操作成功","data":{}}。这能避免前端反复适配不同结构,也方便监控、日志和异常追踪。
在基类中封装 result 方法
最直接有效的方式是在 BaseController 中定义通用响应方法,覆盖日常业务场景:
- 用 protected function success($data = null, $msg = '操作成功', $code = 200) 封装成功响应
- 用 protected function error($msg = '操作失败', $code = 400, $data = null) 封装失败响应
- 两个方法内部均调用
return json(['code' => $code, 'msg' => $msg, 'data' => $data]) - 控制器中只需写
return $this->success($user)或return $this->error('用户名已存在', 1002),无需重复构造数组
全局异常也要走同一套结构
仅封装正常流程不够,验证失败、数据库异常、路由未匹配等都必须落入统一 JSON 格式,否则前端会收到 HTML 错误页或无结构报文:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 在
app\common\exception\Handler.php的render()方法中,先判断是否为 API 请求(如检查 URL 是否以/api/开头,或请求头含Accept: application/json) - 若是,不再返回默认 HTML 页面,而是构造标准 JSON:
return json(['code' => $e->getCode() ?: 500, 'msg' => $e->getMessage(), 'data' => []]) - 特别注意 ValidateException:它默认返回 422 状态码和纯文本错误,需在控制器中捕获后主动抛出带业务码的新异常,或在 Handler 中统一转义其消息为
code/msg/data结构
用中间件兜底拦截所有响应出口
ExceptionHandler 只处理未被捕获的异常,但像模板渲染拦截、中间件提前终止、空响应等情况仍可能漏掉。真正可靠的方案是注册一个全局响应中间件,在响应即将输出前强制统一封装:
立即学习“PHP免费学习笔记(深入)”;
- 新建中间件
app\middleware\UniformJsonResponse.php - 在
handle()中检查响应类型:若当前响应是字符串或数组,且请求属于 API 范围,就用response()->json()重新包装 - 在
app/middleware.php中将其注册为全局中间件,并确保位置在ResponseTrace之后、缓存中间件之前 - 这样即使某处忘了
return json(),也能被兜底修正,大幅提升稳定性
细节决定成败:编码、头信息与输入解析
统一格式不只靠结构,还要保障传输正确性:
- 所有 PHP 文件保存为 UTF-8 无 BOM 格式,否则 JSON 开头会出现不可见字节,导致前端解析失败
- 返回 JSON 前禁止任何输出(
echo、var_dump、Notice 警告),TP6 对空白字符极其敏感 - 跨域请求需显式设置头:
return json($data)->header(['Access-Control-Allow-Origin' => '*']) - 前端发
application/json请求体时,用$this->request->json()获取数据,而非input()—— 后者只处理表单编码


















