4.3 响应构建与 API 资源交付


4.3 响应构建与 API 资源交付

本节摘要:控制器干完活,交付物要发得标准:页面用 view、跳转用 redirect 并带闪存、文件用二进制流、JSON 用 API 资源统一装箱。本节把各类响应的写法过一遍,重点讲 API Resource 这个"打包层"怎么隔离数据库结构与对外契约,让字段改名不再引发客户端连环崩。读完你能为一个模块定出一套稳定的交付规范。

交付物为什么要装箱

工头把活干完,东西不能散着扔出门。散装交付有三个下场:模型字段一改,接口跟着变,客户端全线崩;不同人写的接口,返回结构一人一个样;调试时看不出哪个字段是给谁用的。响应层的任务就是装箱:里面是什么货,外面箱子长什么样,两回事分开管。

四类交付物的基本写法

<?php public function demo(Request $request) { // 一、视图交付:装修队出场(第六章主角) return view('orders.show', ['order' => $order]); // 二、跳转交付:带闪存消息,下一页 flash 取用 return redirect()->route('orders.show', ['order' => $order->id]) ->with('status', '工单已更新'); // 三、文件下载:本地盘或云盘统一走 Storage return Storage::download('reports/2026-08.pdf', '八月报表.pdf'); // 四、JSON 快写:小接口临时用,字段直接定 return response()->json(['ok' => true, 'id' => $order->id], 201); }

跳转那行值得多说一句:with 存进 session 的闪存数据只在下一次请求存活,Blade 里 if (session('status')) 展示一条操作回执,是全 Laravel 最常用的用户反馈通道。响应头与 Cookie 也能链式加工:

<?php return response($content, 200) ->header('Content-Type', 'application/pdf') ->cookie('shift', 'day', 60);

API 资源:给 JSON 定一个装箱标准

接口一多,response()->json 手拼数组就是灾难现场:日期格式不统一、敏感字段漏藏、关联数据想不想带全看当天心情。API 资源(Resource)是模型与 JSON 之间的变换层,装箱规则一处声明:

php artisan make:resource OrderResource
<?php namespace App\Http\Resources; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; class OrderResource extends JsonResource { public function toArray(Request $request): array { return [ 'id' => $this->id, 'sn' => $this->sn, 'title' => $this->title, 'status' => $this->status->label(), // 枚举翻译成中文标签 'budget_yuan' => number_format($this->budget / 100, 2), 'crew' => WorkerResource::collection($this->whenLoaded('workers')), 'created_at' => $this->created_at->toIso8601String(), ]; } }
<?php // 控制器侧:单件用 make,集合用 collection public function show(Order $order): OrderResource { return new OrderResource($order->load('workers')); } public function index(): AnonymousResourceCollection { return OrderResource::collection( Order::with('workers')->latest()->paginate(20) ); }

三个细节体现装箱的价值。whenLoaded 只在关联被预加载时才输出 crew 字段,接口不会偷偷查库;字段名 budget_yuan 是对外契约,库里存分、对外给元,存储结构想怎么改都不影响客户端;日期统一 toIso8601String,全项目一个口径。

图 4-3:散装交付与装箱交付的对比

图 4-3:散装交付与装箱交付的对比

结构化响应与分页约定

列表接口要带上分页信息,资源集合的分页输出天然有序:data 里是本页数据,links 与 meta 里是页码与总数,客户端按同一套约定翻页。状态码的取舍也有一套朴素原则:创建成功 201、删除成功 204、参数不合格 422(上一节验证自动回的)、没登录 401、没权限 403。状态码用对,客户端的错误处理就少一半代码。

💡 关键直觉:接口契约的稳定性比实现省事重要。宁可多写一个 Resource 类,也不要让客户端跟着你的数据库结构过日子——后者省的时间,都会在第一次重构时加倍还回去。

响应层的三个高频追问

Resource 里的条件字段怎么写?
when 条件让字段按需出现:this->when(request->user()?->is_admin, fn () => $this->internal_note) 只对管理员输出内部备注。与 whenLoaded 搭配,一个 Resource 能按调用方身份与加载深度输出不同"装箱规格",且全部声明在一处。

列表的分页信息要不要自己拼?
不要。资源集合接 paginate 后,框架自动输出 data、links、meta 三段结构,总数、当前页、上下页地址齐全,客户端按约定翻页。自己拼分页字段是后面接入新客户端时口径不一致的常见起点。

响应太慢,先查控制器还是先查缓存?
先查数据层。响应慢的罪魁通常是控制器里藏着的循环查询与未预加载关联(第五章的旁听法照搬过来),缓存是数据层干净之后的选项。上手就加缓存的坏处是把"该查得快"的问题盖住了,之后每次失效都是一次卡顿。

本节要点回顾

  • 四类交付:view、redirect 加闪存、Storage 下载、json 快写,各归各位。
  • 装箱层:Resource 隔离库表结构与对外契约,字段加工与敏感信息处理集中一处。
  • whenLoaded:关联输出显式化,接口不偷查库。
  • 状态码约定:201、204、422、401、403 用对位,客户端省一半判断。

工头的活干完了,接下来轮到施工队正式进场:第五章模型施工,从打地基(迁移)到砌数据这栋楼(Eloquent)。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U