Laravel响应JSON怎么写 Laravel如何自定义接口返回 【标准】

3次阅读

Laravel响应JSON怎么写 Laravel如何自定义接口返回 【标准】

直接用 response()->json() 最稳妥

laravel 默认的 json 响应走的就是这个函数,它自动设置 Content-Type: application/json、处理数组/对象序列化、兼容中文不乱码。别自己拼 json_encode() + header(),容易漏状态码或 MIME 类型。

常见错误现象:response()->json($data)->status(200) 写成 response()->json($data, 200) —— 后者第二个参数其实是“JSON 选项”,不是 http 状态码;状态码得用 status() 链式调用或传第三个参数。

  • response()->json(['msg' => 'ok'], 200) ✅ 正确:第二个参数是状态码(仅当没用 status() 时才生效)
  • response()->json(['msg' => 'ok'], JSON_UNESCAPED_UNICODE) ❌ 错误:这会把状态码当成 JSON 选项,返回 500 或空响应
  • 如果要加 JSON 选项(比如不转义中文),写成 response()->json($data, 200, [], JSON_UNESCAPED_UNICODE)

自定义结构统一用 API Resource(别在控制器里硬编码)

接口字段经常要隐藏敏感字段、格式化时间、嵌套关联数据——这些逻辑塞进控制器会让代码越来越难维护,也违背 Laravel 的分层原则。

使用场景:用户列表接口要返回 idnamecreated_at 格式化为 “Y-m-d H:i”,且不返回 passwordemail_verified_at

  • 运行 php artisan make:resource UserResource
  • UserResourcetoArray() 方法里控制输出:return ['id' => $this->id, 'name' => $this->name, 'created_at' => $this->created_at->format('Y-m-d H:i')];
  • 控制器里直接 return new UserResource($user);UserResource::Collection($users);

性能影响:Resource 是惰性求值,不会提前触发 N+1 查询;但别在 toArray() 里写 DB 查询,那会破坏它的设计意图。

全局统一响应格式建议封装到基类或中间件,而非每个接口都写

所谓“标准”响应,比如 { "code": 0, "msg": "success", "data": {} },手动在每个接口里包一层,后期改字段名或加字段会疯掉。

容易踩的坑:有人用中间件统一包裹响应,结果把文件下载、重定向、视图响应也给 JSON 化了,导致 PDF 打不开或跳转失效。

  • 只对 JsonResponse 类型做处理,判断 $response instanceof IlluminateHttpJsonResponse
  • 更推荐方式:写一个基控制器方法,比如 success($data = NULL, $msg = 'success', $code = 0),内部调用 response()->json(compact('code', 'msg', 'data'))
  • 避免在中间件里修改响应体内容,尤其涉及加密、签名等逻辑——它可能被缓存或压缩,顺序难控

ApiResourceJsonResource 别混用,Laravel 9+ 已弃用后者

Laravel 9 开始,JsonResource 被标记为废弃,官方文档和源码都指向 ApiResource(即 IlluminateHttpResourcesJsonJsonResource 的别名)。虽然现在还能用,但升级后会报 E_USER_DEPRECATED。

参数差异很小,但命名和继承路径不同:

  • 旧写法:class UserResource extends JsonResource —— Laravel 8 及以前
  • 新写法:class UserResource extends ApiResource —— Laravel 9+ 推荐,且 ide 支持更好
  • 两者都支持 withoutWrapping()preserveKeys() 等方法,行为一致

兼容性影响:如果你项目还在 Laravel 8,暂时不用急着改;但新项目或准备升级的,直接用 ApiResource 更省心。别等到升级时报一 deprecated warning 才回头翻。

真正复杂的是错误响应的统一处理——比如 404、422、500 怎么也套进你的标准结构里,这部分没法靠 Resource 解决,得配合异常渲染器或 render() 方法定制,而且要小心别把框架原生错误信息暴露出去。

text=ZqhQzanResources