map返回新集合且原集合不变,transform原地修改并返回自身;pluck提取字段需注意嵌套路径与空值处理;when/unless用于链式条件操作;toarray/jsonserialize在大集合中易引发内存与性能问题。

Collection 的 map 和 transform 别混用
两者都改数据,但行为完全不同:map 返回新集合,原集合不变;transform 是原地修改,返回的是当前集合本身(链式调用可用,但容易误以为没变)。
- 查数据时想保留原始集合?必须用
map,比如$items->map(fn($i) => $i->name) - 需要边遍历边改原对象属性(如统一加字段),才用
transform,比如$items->transform(fn($i) => $i->price += 10) - 误用
transform后又想用原数据?会发现已经改掉了——这是最常被吐槽的“丢了原始值”问题
用 pluck 提取字段时注意嵌套和空值
pluck 看似简单,但遇到关联模型或缺失键就容易报错或返回空数组。
- 提取关联字段要写点号路径,比如
$users->pluck('posts.title'),但前提是每个user都有posts关系且不为空,否则对应位置是NULL - 想安全提取(跳过空关系)?得先
Filter或用flatMap,比如$users->flatMap->posts->pluck('title') - 提取后想保持键名?加第二个参数:
$users->pluck('name', 'id'),否则默认是数字索引,丢掉原始 key
when 和 unless 是条件组装集合的真·开关
不是用来做 if 判断的,而是链式流程中动态插入操作——写在哪儿,就在哪儿生效,不打断链式。
- 比如搜索逻辑:
$query->when($request->filled('status'), fn($q) => $q->where('status', $request->status)),只有参数存在才加 where -
unless是反向开关,适合“默认启用,特定条件下关闭”,比如$items->unless($admin, fn($c) => $c->where('published', true)) - 别把它当 PHP 的 if 写进循环里——它只对当前 Collection 实例起作用,且必须返回集合(不能 return null 或 void)
内存敏感场景慎用 toArray 和 jsonSerialize
大集合转数组不是“只是格式变一下”,而是一次深拷贝,尤其含 Eloquent 模型时,会触发所有访问器、追加属性、隐藏字段计算,还可能重复加载关系。
- API 返回前真需要数组?优先考虑
values()+map手动精简字段,比如$items->map->only(['id', 'name']) - 直接
json_encode($collection)其实走的是jsonSerialize,但若模型里重写了该方法,行为可能出人意料 - 调试时用
dd($collection->toArray())很方便,但上线后高频接口里这么干,PHP 内存峰值可能翻倍
Collection 看似轻量,但链式调用每一步都新建对象,嵌套多、数据大、又滥用 toArray 时,性能损耗藏得深,线上才容易暴露