ThinkPHP5 API响应必须通过default_return_type配置+统一封装机制实现标准化。需在模块配置中设'default_return_type'=>'json',并继承ApiController定义success/error方法,同时自定义异常处理器确保所有路径返回结构一致。

ThinkPHP5 的 API 响应结构不能靠“写死 return 数组”来统一,必须通过 default_return_type 配置 + 统一响应封装机制来实现标准输出。否则每个控制器都手动 json(),字段不一致、状态码缺失、错误格式混乱,前端根本没法稳定对接。
配置 default_return_type 控制全局响应类型
这是最基础也最容易被跳过的一步。TP5 不会因为你写了 return ['code'=>0] 就自动转成 JSON —— 它默认走 html 渲染,除非你明确告诉它:“所有 API 响应都要 JSON 化”。
- 在模块级配置文件中(如
application/api/config.php)添加:'default_return_type' => 'json' - 不要改根目录的
config.php,否则前台 HTML 页面也会被强制 JSON 输出,页面直接白屏 - 该配置只影响
return的数组/字符串,不影响你手动调用Response::create()或json()的行为 - 如果同时需要支持 JSON 和 JSONP(比如跨域老接口),得靠路由或中间件动态切换,不能只靠这个配置
统一响应结构必须靠中间件或基类封装,不能靠控制器里硬写
光设 default_return_type 只解决了“格式”,没解决“结构”。你总不能让每个 IndexController 都重复写 return ['code'=>0, 'data'=>$data, 'message'=>'ok'] —— 字段名大小写不统一、code 含义模糊、错误时漏掉 message,都是线上事故前兆。
- 推荐新建
application/api/controller/ApiController.php作为所有 API 控制器的父类 - 在父类中定义
success()和error()方法,强制返回字段、类型、HTTP 状态码 - 例如:
return $this->success(['user'=>$user], '获取成功', 200)→ 自动包装为{'code':0,'data':{...},'message':'获取成功','time':1746802020} - 避免在中间件里做数据包装,因为中间件拿不到控制器返回的原始业务数据结构,容易误包或漏包
json() 助手函数和 Response::create() 的关键区别
这两个都能出 JSON,但适用场景完全不同。用错一个,调试时就多三层日志排查。
立即学习“PHP免费学习笔记(深入)”;
-
json($data):完全绕过配置,无视default_return_type,适合单个接口临时调试或导出功能 -
Response::create($data, 'json'):可链式设置状态码、Header、Callback,适合需要精确控制响应头的场景(如Cache-Control、Content-Type) - 两者都不处理异常 —— 如果数据库查询失败,它们照常执行,不会自动转成
{"code":500,"message":"SQL error"},必须自己 try/catch - 注意:
json($data, 201)中的201是 HTTP 状态码,不是业务code字段,别混在一起用
异常响应也要走同一套结构,否则前端永远 catch 不到业务错误
TP5 默认异常是 HTML 页面,API 场景下必须让它也输出 JSON,并且字段和你正常响应保持一致。否则前端收到 500 状态码 + HTML 内容,解析直接报错。
- 在
application/api/config.php中加:'default_return_type' => 'json'(已提) - 同时确保
exception_handle配置指向自定义异常处理器,例如app\api\exception\Handler - 在 Handler 的
render()方法中,判断是否为 API 请求(可用Request::isAjax()或检查请求头Accept: application/json),再统一返回json(['code'=>500, 'message'=>$e->getMessage()]) - 别依赖
IS_API常量做判断 —— 它只是个标记,不参与实际逻辑,很多项目根本没定义它
真正难的不是怎么输出 JSON,而是让所有路径(正常返回、验证失败、数据库异常、未登录拦截)都从同一个出口吐出结构一致的响应。字段命名、code 含义、嵌套层级、时间戳格式,这些细节一旦放开让各人自由发挥,三个月后连你自己都看不懂返回值了。



















