Collection 是不可变对象,所有操作返回新实例;collect() 仅接受数组或 null,字符串需先 json_decode;Eloquent 结果已是 Collection,勿重复包装;where() 严格匹配,filter() 自定义逻辑;map() 保留键名,需 values() 重索引;RouteCollection 非 Collection,无链式方法。

Collection 不是数组,不能当数组用;它是个对象,所有操作都返回新实例,原集合不变——这点不厘清,后面全会踩坑。
collect() 构造时传 null 或字符串会直接报错
很多人从请求或 API 拿到数据后直接 collect($data),结果遇到 null 或 JSON 字符串就炸了。Laravel 的 collect() 只接受数组或 null(null 会被转为空集合),但字符串、对象、资源句柄一律抛 InvalidArgumentException。
- 安全写法永远是
collect($data ?? []),尤其处理request()->input('tags')这类可能为空的字段 - JSON 字符串必须先
json_decode($json, true),再传给collect();裸传会得到对象或null,不是你要的数组结构 - Eloquent 查询如
User::where()->get()返回的就是Collection,别再套一层collect()——多余且浪费内存
filter() 和 where() 混用导致筛选失效
where() 是字段级严格匹配(===),filter() 是任意逻辑判断。拿 where('status', 'active') 去筛值为 1 或 'ACTIVE' 的字段,结果为空,不是 bug,是设计如此。
-
where('score', null)同时匹配null和0;要只剔null,用whereNotNull('score') -
where('tags', ['php', 'js'])是比整个数组,不是“是否包含 php”;真要查含标签,得用filter(fn($u) => in_array('php', $u['tags'] ?? [])) -
filter()闭包里别省略return,尤其是多行逻辑:map(fn($u) => { return $u->name; }),漏return整个元素变null
map() 后键名乱了,chunk() 和 upsert() 直接失败
map() 默认保留原始键名,比如你对 ['id' => 1, 'name' => 'a'] 执行 map(),结果还是关联数组;但 chunk(10)、upsert()、toArray() 传给前端分页组件时,都依赖连续数字索引。
立即学习“PHP免费学习笔记(深入)”;
- 只要没明确需要保留 ID 键做映射(比如后续要
keyBy('id')),map()后立刻接->values() -
->toArray()和->all()都不重排键,别指望转数组就自动整理 -
mapWithKeys()是特例,它要求闭包返回键值对数组,比如mapWithKeys(fn($u) => [$u->id => $u->name])
RouteCollection 不能当 Collection 用,硬链式调用必报错
RouteCollection 名字带 “Collection”,但和 Illuminate\Support\Collection 完全无关。它没有 map()、filter()、pluck(),甚至连 all() 都没有——它只是个路由查找容器,不是数据集合。
- 遍历只能用
foreach (Route::getRoutes()->getIterator() as $route),拿到的是Illuminate\Routing\Route对象,不是数组 - 想链式筛选,必须先转:
collect(Route::getRoutes()->getRoutes())(注意是getRoutes()方法,不是getIterator()) - 常见误写:
Route::getRoutes()->map(...)—— 这行代码运行时直接抛BadMethodCallException
最常被忽略的其实是不可变性:所有方法返回新实例,$col->filter()->map() 不会影响原始 $col,但很多人在循环里反复赋值又忘了接返回值,最后发现什么都没改。



















