ResourceCollection 传入单模型或 null 会因调用 toBase() 报错;应使用单资源类、手动包装为集合或分页查询;UserResource::collection() 自动映射,而 new UserCollection() 需重写 toArray();分页响应需显式调用 response() 或补充 additional 字段。

ResourceCollection 传入单模型直接报错 toBase() on null
这是最常踩的坑:把 Article::find(1) 或 null 直接塞进 ArticleCollection 构造函数,会立刻触发 Call to a member function toBase() on null。因为 ResourceCollection 内部依赖 Eloquent 集合的 toBase() 方法,而单模型或 null 根本没有这个方法。
实操建议:
- 查详情用单资源类:
new ArticleResource($article),别硬套集合类 - 非要统一返回
data包裹结构?手动包成集合:collect([$article])->filter()(filter()自动剔除null) - 分页场景下永远用
Article::paginate(),它返回的是Paginator实例,ResourceCollection能自动识别并注入links和meta
UserResource::collection() vs new UserCollection() 的行为差异
两者看起来都能处理集合,但底层逻辑不同:UserResource::collection($users) 是静态工厂方法,会自动为每个模型实例调用 UserResource;而 new UserCollection($users) 是实例化一个继承 ResourceCollection 的类,它的 toArray() 默认只返回 $this->collection,不自动委托给单资源类——除非你显式写 $this->collection->mapInto(UserResource::class) 或重写 toArray() 返回 UserResource::collection($this->collection)。
实操建议:
- 想省事且命名规范(如
UserResource对应User模型),优先用UserResource::collection($users) - 需要自定义顶层结构(比如加
summary字段或重命名data键),必须手写UserCollection类并重写toArray() - 别混用:
new UserCollection($users)+UserResource::collection($users)同时存在,容易误判响应结构
分页响应丢失 links/meta 字段的真正原因和修复
Laravel 10+ 默认关闭了对 Paginator 的自动包装。如果你用 new UserCollection(User::paginate(15)) 却只看到纯数组、没 links 和 meta,不是配置问题,是 Laravel 底层 ResourceResponse 不再自动调用 withResponse()。
实操建议:
- 显式调用
->response():UserResource::collection(User::paginate(15))->response() - 或者改用
additional()手动补字段:UserResource::collection($users)->additional(['meta' => ['total' => $users->total()]]),再->response() - 检查是否误写成
new UserResource(User::paginate(15))——这是单资源写法,会直接炸掉
集合里访问未预加载的关系字段导致 N+1
UserCollection 本身不触发查询,但它的每个子项(比如 UserResource)若在 toArray() 里写 $this->posts,而控制器没提前 with('posts'),就会为每条用户数据单独查一次 posts 表。
实操建议:
- 关系加载必须在查询层完成:
User::with('posts', 'profile')->paginate(15),别指望资源类补救 - 资源类中用
$this->whenLoaded('posts'),它只读已加载的数据,不会触发新查询 - 避免在
toArray()里调用$this->load('posts')——运行时加载,照样 N+1
实际项目里最容易被忽略的,是分页器类型判断和集合构造方式的耦合。Laravel 不会帮你猜「这个变量到底是 Paginator 还是普通 Collection」,传错类型,links 就静默消失,连日志都不报错。











