跳转到主要内容

本页目标

本页的目标不是介绍 collect() 的用法,而是为阅读 Laravel 本体的实现代码提供一份地图。 面向的读者:已经熟悉 Collection 方法列表,接下来想理解「为什么会这样设计」的人。

历史变迁

Collection 的结构在引入 LazyCollection 时进行了大规模整理。

Laravel 5.8 之前

  • Illuminate\Support\Collection
  • Illuminate\Database\Eloquent\Collection(继承 Collection
在这个时点还没有 LazyCollectionEnumerableEnumeratesValues

Laravel 6.0 的变化

配合新增的 LazyCollection,将公共 API 拆分到 Enumerable(接口)与 EnumeratesValues(trait)中。

当前整体结构(Laravel 13)

参考:laravel/framework v13.x
实际文件路径是 src/Illuminate/Collections/*,但命名空间仍保持为 Illuminate\Support。阅读代码时请分别确认「路径」和「namespace」。

PHPDoc 与 PHPStan 风格的 Generics

PHP 本身没有 Generics。 但在 Collection 周边,通过 PHPDoc 表达了强类型信息。 主要目的有两个:
  • 让 IDE 补全更准确
  • 提升 PHPStan / Larastan 等静态分析的精度

常见写法

在 Eloquent Collection 中的呈现

由于 TValue 具体化为 TModelmap()filter() 等方法的类型推断会向 Eloquent 模型倾斜,从而得到更强的类型提示。

阅读实现代码的顺序

1. 从入口 Enumerable 开始读

先掌握「提供了什么契约」。 在这里把握方法列表后,后续阅读实现会更快。

2. 在 EnumeratesValues 中追踪公共方法

mapfilterreduce 等大部分公共逻辑都在这里。 之后只看 CollectionLazyCollection 的差异部分,可减少无谓的通读。

3. 查看 CollectionLazyCollection 的差异

  • Collection:持有数组并立即求值
  • LazyCollection:使用 Generator 进行惰性求值
同名方法的求值时机与内存特性不同。

4. 最后阅读 Eloquent\Collection

聚焦 findloadmodelKeys 等针对模型集合的扩展。 理解基础的 Collection 后再看,更容易看清其意图。
深入分析某个方法时,按「Enumerable 的声明 → EnumeratesValues 的主体 → Collection / LazyCollection 是否覆盖」的顺序追踪,就不会迷路。

相关页面

最后修改于 2026年7月18日