必须用 resource 类做 api 数据格式转换,它是数据出口的强制闸门,统一管控字段、关联、安全与格式化;toarray() 是唯一可信入口,需显式定义所有输出字段,配合 whenloaded() 防 n+1,集合资源须用 collection() 方法并单独建集合类。

必须用 Resource 类做 API 数据格式转换,而不是直接 toArray() 或手动构造数组——否则字段控制、关联加载、条件输出、安全性(如隐藏密码)全得在控制器里硬写,很快失控。
Resource 类的 toArray() 是唯一可信的数据出口
所有字段定义、格式化、条件判断都必须收口到 toArray() 方法里。它不是“可选装饰”,而是数据流的强制闸门。
- 模型属性访问(
$this->name)会自动触发访问器,但仅当该属性被显式写入toArray()返回数组时才生效;漏写就等于不输出 - 关联数据必须用
$this->relation访问,不能依赖预加载后直接读$this->posts->first()—— 集合资源里这会报错或返回空 - 日期字段别直接
$this->created_at->format('Y-m-d'),优先用$this->created_at?->toDateString()防 null - 不要在
toArray()里调用模型方法做复杂查询(比如$this->getLatestOrder()),那会破坏资源的无状态性,改用闭包 +whenLoaded()
UserResource::collection() 不是语法糖,它绕过了单个资源的构造逻辑
集合资源不是“把每个模型 new 一遍再塞进数组”,而是批量处理、跳过中间实例化,性能更好,也避免了 __construct() 中可能存在的副作用。
- 传入空集合(
collect([]))时,UserResource::collection()返回空数组[],而new UserResource($user)传 null 会直接报错 - 如果你重写了
UserResource的构造函数(比如加日志或缓存),collection()完全不走它——这点常被忽略 - 想给集合加额外字段(如分页元信息),必须单独建集合类(
php artisan make:resource UserCollection),不能只靠collection()静态方法
whenLoaded() 是防止 N+1 的关键开关,不是可有可无的优化
它只在关联已被预加载(with('posts'))时才执行内部逻辑,否则跳过。没它,$this->posts 在未预加载时会触发懒加载,一次请求查出几十次数据库。
- 错误写法:
'posts' => $this->posts—— 看似简洁,实则危险 - 正确写法:
'posts' => $this->whenLoaded('posts', fn() => PostResource::collection($this->posts)) - 如果关联名是嵌套的(如
company.address),whenLoaded()只支持一级,得拆成两层判断 -
whenLoaded()内部仍可嵌套when()做业务逻辑过滤,但别放耗时操作
真正容易被忽略的点:资源类里没有 $request 上下文时,when() 和 whenLoaded() 的判断依据全靠模型当前状态和已加载关系——这意味着你无法在资源里做“根据用户权限动态决定是否显示字段”这类事,得提前在控制器里把权限结果作为属性塞进模型,或改用策略资源(Policy-based Resource)。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











