跳转到主要内容

本页目标

本页的目标不是介绍 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 等静态分析的精度

常见写法

/**
 * @template TKey of array-key
 * @template-covariant TValue
 * @implements \Illuminate\Support\Enumerable<TKey, TValue>
 */
class Collection implements Enumerable
{
    /**
     * @use \Illuminate\Support\Traits\EnumeratesValues<TKey, TValue>
     */
    use EnumeratesValues;
}
写法含义
@template TKey of array-key将 Key 类型约束为 int|string
@template-covariant TValue将 Value 类型作为协变处理(更容易安全地替换为更具体的类型)
@implements ...<TKey, TValue>向实现的接口传递类型参数
@extends ...<TKey, TModel>声明继承父类时的类型参数
@use ...<TKey, TValue>声明使用 trait 时的类型参数

在 Eloquent Collection 中的呈现

/**
 * @template TKey of array-key
 * @template TModel of \Illuminate\Database\Eloquent\Model
 * @extends \Illuminate\Support\Collection<TKey, TModel>
 */
class Collection extends BaseCollection
{
}
由于 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月13日