ThinkPHP 6 推荐用 json() 而非 success(),因后者是固定结构的语义化封装(code=1/msg/data),不可配置 HTTP 状态码与字段名;json() 支持自定义结构、状态码(如 201)、响应头及编码,适用于标准 RESTful API。

ThinkPHP 6 的 json() 和 success() 到底该用哪个
API 成功返回,核心是「状态码 + 数据结构 + 语义清晰」。ThinkPHP 6 默认推荐用 json(),不是 success() ——后者只是封装了 json() 的语法糖,且默认状态码是 200,无法覆盖如 201(Created)、204(No Content)等真实场景。
常见错误:直接写 return success('ok', $data),结果前端拿不到 status 字段、或 HTTP 状态码错配、或字段名不统一(比如有的叫 code,有的叫 status)。
-
success()是think\facade\Response提供的快捷方法,固定返回['code' => 1, 'msg' => ..., 'data' => ...],不可配置字段名和状态码 - 需要自定义结构(如遵循 RESTful 规范或团队 API 协议)时,必须用
json()手动构造 - 若需设置 HTTP 状态码(如新增资源返回 201),只能用
json($data)->code(201)
怎么写出符合前后端约定的成功响应体
多数项目要求统一格式,例如:{ "code": 0, "message": "success", "data": {...} }。ThinkPHP 不内置这种约定,得自己封装或在控制器里手动写。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 在基类控制器里加一个
apiSuccess()方法,返回json(['code' => 0, 'message' => $msg ?: 'success', 'data' => $data]) - 避免在每个接口里重复写
json([...]),但也不要过度抽象成“全局响应中间件”——它会干扰文件下载、跳转等非 JSON 场景 - 如果用了
think-orm,注意toArray()默认不包含隐藏字段($hidden),而json()直接序列化对象会触发完整输出,可能泄露敏感字段
返回空数据或分页结果时容易漏掉的点
返回空数组、空对象、分页数据时,结构一致性比“有没有数据”更重要。前端常靠 data 是否为数组判断列表渲染,靠 data 是否为对象判断详情。
- 列表接口不要写
json($list),而应写json(['list' => $list, 'total' => $count])或按协议返回data+meta - 空数据别返回
null,否则 JSON 变成"data": null,前端解构报错;统一用[]或{} - 使用
paginate()时,$page->items()是集合,$page->toArray()包含data、current_page等,但字段名和外层结构仍需手动包裹,不能直接json($page)
调试时怎么看实际返回内容是否合规
别只信浏览器地址栏打开接口看 JSON ——那走的是 GET,可能触发缓存、缺少 Accept: application/json 头,甚至被中间件重定向。
- 用
curl -H "Accept: application/json" http://test.com/api/user看原始响应头和 body - 检查响应头中
Content-Type是否为application/json; charset=utf-8;不是?说明没走json(),可能是忘了return或被view()拦截 - 遇到中文乱码,不是编码问题,而是响应头缺失
charset=utf-8,用json($data)->contentType('application/json; charset=utf-8')显式指定



















