翻译进度
45
分块数量
4
参与人数

集合

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


集合

简介

Illuminate\Support\Collection 类为处理数据数组提供了一个流畅、便捷的封装。例如,查看下面的代码。我们使用 collect 辅助函数从数组创建一个新的集合实例,对每个元素运行 strtoupper 函数,然后移除所有空元素:

$collection = collect(['Taylor', 'Abigail', null])->map(function (?string $name) {
    return strtoupper($name);
})->reject(function (string $name) {
    return empty($name);
});

如您所见,Collection 类允许您链式调用其方法以对底层数组执行流畅的映射和缩减。通常,集合是不可变的,这意味着每个 Collection 方法都会返回一个全新的 Collection 实例。

创建集合

如上所述,collect 辅助函数为给定数组返回一个新的 Illuminate\Support\Collection 实例。因此,创建一个集合非常简单:

$collection = collect([1, 2, 3]);

您也可以使用 makefromJson 方法创建集合。

[!NOTE]
Eloquent 查询的结果总是以 Collection 实例的形式返回。

扩展集合

集合是“可宏扩展的”,这允许您在运行时向 Collection 类添加额外的方法。Illuminate\Support\Collection 类的 macro 方法接受一个闭包,该闭包将在调用宏时执行。宏闭包可以通过 $this 访问集合的其他方法,就像它是集合类的真实方法一样。例如,以下代码向 Collection 类添加了一个 toUpper 方法:

use Illuminate\Support\Collection;
use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
    return $this->map(function (string $value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']
Senkorl 翻译于 1个月前

通常,您应该在服务提供者boot 方法中声明集合宏。

宏参数

如果需要,您可以定义接受额外参数的宏:

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Lang;

Collection::macro('toLocale', function (string $locale) {
    return $this->map(function (string $value) use ($locale) {
        return Lang::get($value, [], $locale);
    });
});

$collection = collect(['first', 'second']);

$translated = $collection->toLocale('es');

可用方法

在集合文档的剩余大部分内容中,我们将讨论 Collection 类上可用的每个方法。请记住,所有这些方法都可以链式调用,以流畅地操作底层数组。此外,几乎每个方法都会返回一个新的 Collection 实例,允许您在需要时保留集合的原始副本:

Senkorl 翻译于 1个月前

方法列表

after()

after 方法返回给定项之后的项。如果未找到给定项或该项是最后一项,则返回 null

$collection = collect([1, 2, 3, 4, 5]);

$collection->after(3);

// 4

$collection->after(5);

// null

此方法使用"松散"比较搜索给定项,这意味着包含整数值的字符串将被视为等于相同值的整数。要使用"严格"比较,您可以向方法提供 strict 参数:

collect([2, 4, 6, 8])->after('4', strict: true);

// null

或者,您可以提供自己的闭包来搜索通过给定真值测试的第一个项:

collect([2, 4, 6, 8])->after(function (int $item, int $key) {
    return $item > 5;
});

// 8

all()

all 方法返回集合所代表的底层数组:

collect([1, 2, 3])->all();

// [1, 2, 3]

average()

avg 方法的别名。

avg()

avg 方法返回给定键的平均值

$average = collect([
    ['foo' => 10],
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 40]
])->avg('foo');

// 20

$average = collect([1, 1, 2, 4])->avg();

// 2

before()

before 方法与 after 方法相反。它返回给定项之前的项。如果未找到给定项或该项是第一项,则返回 null

$collection = collect([1, 2, 3, 4, 5]);

$collection->before(3);

// 2

$collection->before(1);

// null

collect([2, 4, 6, 8])->before('4', strict: true);

// null

collect([2, 4, 6, 8])->before(function (int $item, int $key) {
    return $item > 5;
});

// 4
Senkorl 翻译于 1个月前

chunk()

chunk 方法将集合拆分为多个较小的集合,每个集合的大小由你指定:

$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->all();

// [[1, 2, 3, 4], [5, 6, 7]]

此方法在使用网格系统(如 Bootstrap)的视图中非常有用。例如,假设你有一个要在网格中显示的 Eloquent 模型集合:

@foreach ($products->chunk(3) as $chunk)
    <div class="row">
        @foreach ($chunk as $product)
            <div class="col-xs-4">{{ $product->name }}</div>
        @endforeach
    </div>
@endforeach

chunkWhile()

chunkWhile 方法根据给定回调的返回值,将集合拆分为多个较小的集合。传递给闭包的 $chunk 变量可以用来检查前一个元素:

$collection = collect(str_split('AABBCCCD'));

$chunks = $collection->chunkWhile(function (string $value, int $key, Collection $chunk) {
    return $value === $chunk->last();
});

$chunks->all();

// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]

collapse()

collapse 方法将一个包含数组或集合的集合,合并成一个单一的扁平集合:

$collection = collect([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]);

$collapsed = $collection->collapse();

$collapsed->all();

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

collapseWithKeys()

collapseWithKeys 方法将一个包含数组或集合的集合扁平化为单一集合,同时保持原始键名不变:

$collection = collect([
    ['first'  => collect([1, 2, 3])],
    ['second' => [4, 5, 6]],
    ['third'  => collect([7, 8, 9])]
]);

$collapsed = $collection->collapseWithKeys();

$collapsed->all();

// [
//     'first'  => [1, 2, 3],
//     'second' => [4, 5, 6],
//     'third'  => [7, 8, 9],
// ]

collect()

collect 方法返回一个新的 Collection 实例,包含当前集合中的所有项:

$collectionA = collect([1, 2, 3]);

$collectionB = $collectionA->collect();

$collectionB->all();

// [1, 2, 3]
无与伦比 翻译于 1周前

collect 方法主要用于将懒集合转换为标准的 Collection 实例:

$lazyCollection = LazyCollection::make(function () {
    yield 1;
    yield 2;
    yield 3;
});

$collection = $lazyCollection->collect();

$collection::class;

// 'Illuminate\Support\Collection'

$collection->all();

// [1, 2, 3]

[!注意]
当你拥有一个 Enumerable 实例并且需要一个非懒集合实例时,collect 方法特别有用。由于 collect()Enumerable 合约的一部分,你可以安全地使用它获取一个 Collection 实例。

combine()

combine 方法将集合中的值作为键,与另一个数组或集合中的值组合起来:

$collection = collect(['name', 'age']);

$combined = $collection->combine(['George', 29]);

$combined->all();

// ['name' => 'George', 'age' => 29]

concat()

concat 方法会将给定数组或集合的值追加到原集合的末尾:

$collection = collect(['John Doe']);

$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);

$concatenated->all();

// ['John Doe', 'Jane Doe', 'Johnny Doe']

concat 方法会对追加到原集合的元素重新按数字索引进行排序。
如果想在关联集合中保持原有键,请使用 merge 方法。

contains()

contains 方法用于判断集合是否包含某个元素。
你可以传递一个闭包给 contains 方法,以判断集合中是否存在满足给定条件的元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->contains(function (int $value, int $key) {
    return $value > 5;
});

// false

另外,你也可以直接传递一个值给 contains 方法,以判断集合中是否包含该值:

$collection = collect(['name' => 'Desk', 'price' => 100]);

$collection->contains('Desk');

// true

$collection->contains('New York');

// false
无与伦比 翻译于 1周前

你也可以向 contains 方法传递一个键/值对,用于判断集合中是否存在该键值对:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
]);

$collection->contains('product', 'Bookcase');

// false

contains 方法在检查元素值时使用“宽松”(loose)比较,这意味着一个字符串形式的整数会被视为等于相同值的整数。
如果需要使用“严格”(strict)比较,请使用 containsStrict 方法。

如果想要获取 contains 的反向结果,请使用 doesntContain 方法。

containsOneItem()

containsOneItem 方法用于判断集合是否只包含一个元素:

collect([])->containsOneItem();

// false

collect(['1'])->containsOneItem();

// true

collect(['1', '2'])->containsOneItem();

// false

collect([1, 2, 3])->containsOneItem(fn (int $item) => $item === 2);

// true

containsStrict()

该方法与 contains 方法的签名相同,但所有值都会使用“严格”比较进行判断。

[!注意]
在使用 Eloquent 集合 时,该方法的行为会有所不同。

count()

count 方法返回集合中元素的总数:

$collection = collect([1, 2, 3, 4]);

$collection->count();

// 4

countBy()

countBy 方法用于统计集合中值的出现次数。
默认情况下,它会统计每个元素的出现次数,从而可以统计集合中某类元素的数量:

$collection = collect([1, 2, 2, 2, 3]);

$counted = $collection->countBy();

$counted->all();

// [1 => 1, 2 => 3, 3 => 1]

你也可以向 countBy 方法传递一个闭包,以自定义统计逻辑:

$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']);

$counted = $collection->countBy(function (string $email) {
    return substr(strrchr($email, '@'), 1);
});

$counted->all();

// ['gmail.com' => 2, 'yahoo.com' => 1]
无与伦比 翻译于 1周前

crossJoin()

crossJoin 方法会将集合的值与给定的数组或集合进行交叉连接(Cross Join),返回一个笛卡尔积(Cartesian product),即所有可能排列组合的结果:

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b']);

$matrix->all();

/*
    [
        [1, 'a'],
        [1, 'b'],
        [2, 'a'],
        [2, 'b'],
    ]
*/

$collection = collect([1, 2]);

$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);

$matrix->all();

/*
    [
        [1, 'a', 'I'],
        [1, 'a', 'II'],
        [1, 'b', 'I'],
        [1, 'b', 'II'],
        [2, 'a', 'I'],
        [2, 'a', 'II'],
        [2, 'b', 'I'],
        [2, 'b', 'II'],
    ]
*/

dd()

dd 方法会输出集合中的所有项目,并立即终止脚本执行

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dd();

/*
    array:2 [
        0 => "John Doe"
        1 => "Jane Doe"
    ]
*/

如果你不希望中断脚本执行,可以使用 dump 方法代替。

diff()

diff 方法会根据将当前集合与另一个集合或普通 PHP 数组进行比较。
它会返回那些在原集合中存在,但不在给定集合中存在的值:

$collection = collect([1, 2, 3, 4, 5]);

$diff = $collection->diff([2, 4, 6, 8]);

$diff->all();

// [1, 3, 5]

[!NOTE]
当使用 Eloquent 集合 时,此方法的行为会有所不同。

diffAssoc()

diffAssoc 方法会根据键和值将当前集合与另一个集合或普通 PHP 数组进行比较。
它会返回那些在原集合中存在但不在给定集合中存在的键值对:

$collection = collect([
    'color' => 'orange',
    'type' => 'fruit',
    'remain' => 6,
]);

$diff = $collection->diffAssoc([
    'color' => 'yellow',
    'type' => 'fruit',
    'remain' => 3,
    'used' => 6,
]);

$diff->all();

// ['color' => 'orange', 'remain' => 6]
无与伦比 翻译于 6天前

diffAssocUsing()

diffAssoc 不同,diffAssocUsing 方法允许你传入一个自定义回调函数来比较键名(索引):

$collection = collect([
    'color' => 'orange',
    'type' => 'fruit',
    'remain' => 6,
]);

$diff = $collection->diffAssocUsing([
    'Color' => 'yellow',
    'Type' => 'fruit',
    'Remain' => 3,
], 'strnatcasecmp');

$diff->all();

// ['color' => 'orange', 'remain' => 6]

这个回调函数必须是一个比较函数,它需要返回一个整数:

  • 小于 0 表示第一个参数小于第二个参数;
  • 等于 0 表示两者相等;
  • 大于 0 表示第一个参数大于第二个参数。

更多信息请参考 PHP 文档中关于 array_diff_uassoc 的说明。
diffAssocUsing 方法在内部正是基于此函数实现的。

diffKeys()

diffKeys 方法根据键名将当前集合与另一个集合或普通 PHP 数组进行比较。
它会返回那些在原集合中存在但不在给定集合中存在的键值对:

$collection = collect([
    'one' => 10,
    'two' => 20,
    'three' => 30,
    'four' => 40,
    'five' => 50,
]);

$diff = $collection->diffKeys([
    'two' => 2,
    'four' => 4,
    'six' => 6,
    'eight' => 8,
]);

$diff->all();

// ['one' => 10, 'three' => 30, 'five' => 50]

doesntContain()

doesntContain 方法用于判断集合是否不包含指定的项目。
你可以传入一个闭包(回调函数)来判断集合中是否不存在满足特定条件的元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->doesntContain(function (int $value, int $key) {
    return $value < 5;
});

// false

也可以直接传入一个字符串或值来判断集合中是否不包含指定的值:

$collection = collect(['name' => 'Desk', 'price' => 100]);

$collection->doesntContain('Table');

// true

$collection->doesntContain('Desk');

// false

还可以传入一个键 / 值对来判断集合中是否不存在该键值组合:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
]);

$collection->doesntContain('product', 'Bookcase');

// true
无与伦比 翻译于 6天前

doesntContain 方法在检查项目值时使用宽松(loose)比较,这意味着字符串形式的数字会被视为与相同值的整数相等

dot()

dot 方法会将一个多维集合扁平化为单层集合,并使用“点号(dot)”表示层级关系:

$collection = collect(['products' => ['desk' => ['price' => 100]]]);

$flattened = $collection->dot();

$flattened->all();

// ['products.desk.price' => 100]

dump()

dump 方法会输出集合中的所有项目:

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dump();

/*
    array:2 [
        0 => "John Doe"
        1 => "Jane Doe"
    ]
*/

如果你希望在输出后终止脚本执行,请改用 dd 方法。

duplicates()

duplicates 方法用于从集合中获取并返回重复的值

$collection = collect(['a', 'b', 'a', 'c', 'b']);

$collection->duplicates();

// [2 => 'a', 4 => 'b']

如果集合中包含数组或对象,你可以传入一个属性键名,指定要检查哪个字段的重复值:

$employees = collect([
    ['email' => 'abigail@example.com', 'position' => 'Developer'],
    ['email' => 'james@example.com', 'position' => 'Designer'],
    ['email' => 'victoria@example.com', 'position' => 'Developer'],
]);

$employees->duplicates('position');

// [2 => 'Developer']

duplicatesStrict()

此方法与 duplicates 方法具有相同的用法,但会使用严格(strict)比较来判断值是否相等。

each()

each 方法会遍历集合中的每个项目,并将项目传递给一个闭包函数:

$collection = collect([1, 2, 3, 4]);

$collection->each(function (int $item, int $key) {
    // ...
});

如果希望在遍历过程中中断循环,可以在闭包中返回 false

$collection->each(function (int $item, int $key) {
    if (/* condition */) {
        return false;
    }
});
无与伦比 翻译于 6天前

eachSpread()

eachSpread 方法会遍历集合中的项目,并将每个嵌套项的值依次传递给指定的回调函数:

$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);

$collection->eachSpread(function (string $name, int $age) {
    // ...
});

你可以通过在回调函数中返回 false停止遍历

$collection->eachSpread(function (string $name, int $age) {
    return false;
});

ensure()

ensure 方法用于验证集合中的所有元素是否属于指定的类型或类型列表。
如果存在不符合要求的元素,将抛出 UnexpectedValueException 异常:

return $collection->ensure(User::class);

return $collection->ensure([User::class, Customer::class]);

你也可以指定原始类型(primitive types),如 stringintfloatboolarray

return $collection->ensure('int');

[!WARNING]
ensure 方法并不能保证在之后的操作中不会再向集合中添加不同类型的元素。

every()

every 方法用于验证集合中的所有元素是否都通过给定的条件判断(truth test)

collect([1, 2, 3, 4])->every(function (int $value, int $key) {
    return $value > 2;
});

// false

如果集合为空,every 方法将返回 true

$collection = collect([]);

$collection->every(function (int $value, int $key) {
    return $value > 2;
});

// true

except()

except 方法会返回集合中除指定键之外的所有项目:

$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);

$filtered = $collection->except(['price', 'discount']);

$filtered->all();

// ['product_id' => 1]

若要获取与 except 相反的结果,请参阅 only 方法。

[!注意]
当使用 Eloquent 集合 时,此方法的行为会有所不同。

无与伦比 翻译于 6天前

filter()

filter 方法使用给定的回调函数过滤集合,仅保留那些通过指定条件判断(truth test)的项目:

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->filter(function (int $value, int $key) {
    return $value > 2;
});

$filtered->all();

// [3, 4]

如果没有传入回调函数,filter 会移除集合中所有等价于 false 的元素(即假值,如 nullfalse''0、空数组等):

$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

想要获取与 filter 相反的结果,请参阅 reject 方法。

first()

first 方法会返回集合中第一个通过指定条件判断的元素

collect([1, 2, 3, 4])->first(function (int $value, int $key) {
    return $value > 2;
});

// 3

你也可以在不传递任何参数的情况下调用 first 方法,以获取集合中的第一个元素
如果集合为空,则返回 null

collect([1, 2, 3, 4])->first();

// 1

firstOrFail()

firstOrFail 方法与 first 方法功能相同;但如果未找到任何结果,则会抛出
Illuminate\Support\ItemNotFoundException 异常:

collect([1, 2, 3, 4])->firstOrFail(function (int $value, int $key) {
    return $value > 5;
});

// 抛出 ItemNotFoundException 异常...

同样地,如果在不传入回调的情况下调用该方法,而集合又是空的,
也会抛出 ItemNotFoundException 异常:

collect([])->firstOrFail();

// 抛出 ItemNotFoundException 异常...

firstWhere()

firstWhere 方法会返回集合中第一个符合给定键 / 值条件的元素:

$collection = collect([
    ['name' => 'Regena', 'age' => null],
    ['name' => 'Linda', 'age' => 14],
    ['name' => 'Diego', 'age' => 23],
    ['name' => 'Linda', 'age' => 84],
]);

$collection->firstWhere('name', 'Linda');

// ['name' => 'Linda', 'age' => 14]
无与伦比 翻译于 6天前

你也可以在调用 firstWhere 方法时使用比较运算符

$collection->firstWhere('age', '>=', 18);

// ['name' => 'Diego', 'age' => 23]

where 方法类似,你也可以只传递一个参数给 firstWhere 方法。
在这种情况下,firstWhere 会返回集合中第一个给定键的值为“真”(truthy)的元素:

$collection->firstWhere('age');

// ['name' => 'Linda', 'age' => 14]

flatMap()

flatMap 方法会遍历集合中的每个元素,并将每个值传递给指定的闭包。
闭包可以自由地修改并返回该元素,从而形成一个新的集合。
之后,该集合会被扁平化一层

$collection = collect([
    ['name' => 'Sally'],
    ['school' => 'Arkansas'],
    ['age' => 28]
]);

$flattened = $collection->flatMap(function (array $values) {
    return array_map('strtoupper', $values);
});

$flattened->all();

// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];

flatten()

flatten 方法会将一个多维集合扁平化为单层集合

$collection = collect([
    'name' => 'Taylor',
    'languages' => [
        'PHP', 'JavaScript'
    ]
]);

$flattened = $collection->flatten();

$flattened->all();

// ['Taylor', 'PHP', 'JavaScript'];

如有需要,你可以为 flatten 方法传入一个“深度”(depth)参数,用来指定要扁平化的层级数:

$collection = collect([
    'Apple' => [
        [
            'name' => 'iPhone 6S',
            'brand' => 'Apple'
        ],
    ],
    'Samsung' => [
        [
            'name' => 'Galaxy S7',
            'brand' => 'Samsung'
        ],
    ],
]);

$products = $collection->flatten(1);

$products->values()->all();

/*
    [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
        ['name' => 'Galaxy S7', 'brand' => 'Samsung'],
    ]
*/

在上面的例子中,如果不传入 depth 参数直接调用 flatten
结果会进一步展开成:
['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']
通过指定“深度”,你可以控制扁平化操作应当展开的嵌套层级数量。

无与伦比 翻译于 6天前

flip()

flip 方法会交换集合中的键和值

$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);

$flipped = $collection->flip();

$flipped->all();

// ['Taylor' => 'name', 'Laravel' => 'framework']

forget()

forget 方法会根据键名从集合中移除一个项目:

$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);

// 删除单个键...
$collection->forget('name');

// ['framework' => 'Laravel']

// 删除多个键...
$collection->forget(['name', 'framework']);

// []

[!警告]
与大多数其他集合方法不同,forget 不会返回一个新的集合实例
它会直接修改原集合并返回自身。

forPage()

forPage 方法会返回一个新的集合,其中包含指定页码上的项目。
该方法的第一个参数是页码,第二个参数是每页显示的项目数量

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunk = $collection->forPage(2, 3);

$chunk->all();

// [4, 5, 6]

fromJson()

静态方法 fromJson 会通过 PHP 的 json_decode 函数解码给定的 JSON 字符串,
并据此创建一个新的集合实例:

use Illuminate\Support\Collection;

$json = json_encode([
    'name' => 'Taylor Otwell',
    'role' => 'Developer',
    'status' => 'Active',
]);

$collection = Collection::fromJson($json);

get()

get 方法根据指定的键名返回对应的项目。
如果键不存在,则返回 null

$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);

$value = $collection->get('name');

// Taylor

你还可以传入一个默认值作为第二个参数:
当键不存在时,将返回该默认值:

$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);

$value = $collection->get('age', 34);

// 34
无与伦比 翻译于 6天前

你甚至可以将回调函数作为方法的默认值传入。如果指定的键不存在,那么回调函数的返回结果将会被返回:

$collection->get('email', function () {
    return 'taylor@example.com';
});

// taylor@example.com

groupBy()

groupBy 方法会根据给定的键将集合中的项目进行分组:

$collection = collect([
    ['account_id' => 'account-x10', 'product' => 'Chair'],
    ['account_id' => 'account-x10', 'product' => 'Bookcase'],
    ['account_id' => 'account-x11', 'product' => 'Desk'],
]);

$grouped = $collection->groupBy('account_id');

$grouped->all();

/*
    [
        'account-x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'account-x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

除了传入字符串形式的键,你也可以传入一个回调函数。该回调函数应返回用于分组的值:

$grouped = $collection->groupBy(function (array $item, int $key) {
    return substr($item['account_id'], -3);
});

$grouped->all();

/*
    [
        'x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

可以通过传入数组来指定多个分组条件。数组中的每个元素会应用于多维数组中对应层级的分组:

$data = new Collection([
    10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
    20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
    30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
    40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
]);

$result = $data->groupBy(['skill', function (array $item) {
    return $item['roles'];
}], preserveKeys: true);

/*
[
    1 => [
        'Role_1' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_2' => [
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_3' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
        ],
    ],
    2 => [
        'Role_1' => [
            30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
        ],
        'Role_2' => [
            40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
        ],
    ],
];
*/
无与伦比 翻译于 5天前

has()

has 方法用于判断集合中是否存在指定的键:

$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);

$collection->has('product');

// true

$collection->has(['product', 'amount']);

// true

$collection->has(['amount', 'price']);

// false

hasAny()

hasAny 方法用于判断给定的键中是否有任意一个存在于集合中:

$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);

$collection->hasAny(['product', 'price']);

// true

$collection->hasAny(['name', 'price']);

// false

implode()

implode 方法用于将集合中的项目连接成字符串。
其参数取决于集合中项目的类型。
如果集合包含数组或对象,你应该传入要连接的属性键名,以及连接它们时使用的“连接符”字符串:

$collection = collect([
    ['account_id' => 1, 'product' => 'Desk'],
    ['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// 'Desk, Chair'

如果集合中包含的是简单的字符串或数值,你只需传入一个“连接符”作为参数:

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

如果你想在连接前格式化这些值,可以向 implode 方法传入一个闭包:

$collection->implode(function (array $item, int $key) {
    return strtoupper($item['product']);
}, ', ');

// 'DESK, CHAIR'

intersect()

intersect 方法会从原集合中移除那些不在给定数组或集合中的值。
结果集合会保留原集合的键:

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

[!注意]
当使用 Eloquent 集合 时,此方法的行为会有所不同。

无与伦比 翻译于 5天前

intersectUsing()

intersectUsing 方法会从原集合中移除那些不在给定数组或集合中的值,并使用自定义回调函数来比较这些值。
结果集合会保留原集合的键:

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersectUsing(['desk', 'chair', 'bookcase'], function (string $a, string $b) {
    return strcasecmp($a, $b);
});

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

intersectAssoc()

intersectAssoc 方法将原集合与另一个集合或数组进行比较,
返回那些在所有给定集合中都存在的键 / 值对:

$collection = collect([
    'color' => 'red',
    'size' => 'M',
    'material' => 'cotton'
]);

$intersect = $collection->intersectAssoc([
    'color' => 'blue',
    'size' => 'M',
    'material' => 'polyester'
]);

$intersect->all();

// ['size' => 'M']

intersectAssocUsing()

intersectAssocUsing 方法将原集合与另一个集合或数组进行比较,
返回两者中都存在的键 / 值对,并使用自定义的比较回调函数来判断键和值是否相等:

$collection = collect([
    'color' => 'red',
    'Size' => 'M',
    'material' => 'cotton',
]);

$intersect = $collection->intersectAssocUsing([
    'color' => 'blue',
    'size' => 'M',
    'material' => 'polyester',
], function (string $a, string $b) {
    return strcasecmp($a, $b);
});

$intersect->all();

// ['Size' => 'M']

intersectByKeys()

intersectByKeys 方法会从原集合中移除那些键(及其对应的值)不在给定数组或集合中的项目:

$collection = collect([
    'serial' => 'UX301', 'type' => 'screen', 'year' => 2009,
]);

$intersect = $collection->intersectByKeys([
    'reference' => 'UX404', 'type' => 'tab', 'year' => 2011,
]);

$intersect->all();

// ['type' => 'screen', 'year' => 2009]
无与伦比 翻译于 5天前

isEmpty()

isEmpty 方法在集合为空时返回 true,否则返回 false

collect([])->isEmpty();

// true

isNotEmpty()

isNotEmpty 方法在集合不为空时返回 true,否则返回 false

collect([])->isNotEmpty();

// false

join()

join 方法使用一个字符串将集合中的值连接起来。
通过该方法的第二个参数,你还可以指定在连接最后一个元素时所使用的字符串:

collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''

keyBy()

keyBy 方法会根据给定的键为集合重新建立键名。
如果多个项目具有相同的键,只有最后一个会出现在新的集合中:

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keyed = $collection->keyBy('product_id');

$keyed->all();

/*
    [
        'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

你也可以向该方法传入一个回调函数。
该回调函数应返回用于作为键名的值:

$keyed = $collection->keyBy(function (array $item, int $key) {
    return strtoupper($item['product_id']);
});

$keyed->all();

/*
    [
        'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/
无与伦比 翻译于 5天前

keys()

keys 方法返回集合中所有的键:

$collection = collect([
    'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
    'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$keys = $collection->keys();

$keys->all();

// ['prod-100', 'prod-200']

last()

last 方法返回集合中最后一个通过给定条件测试的元素:

collect([1, 2, 3, 4])->last(function (int $value, int $key) {
    return $value < 3;
});

// 2

你也可以不传入任何参数来获取集合中的最后一个元素。
如果集合为空,则返回 null

collect([1, 2, 3, 4])->last();

// 4

lazy()

lazy 方法会基于集合的底层数组返回一个新的 LazyCollection 实例:

$lazyCollection = collect([1, 2, 3, 4])->lazy();

$lazyCollection::class;

// Illuminate\Support\LazyCollection

$lazyCollection->all();

// [1, 2, 3, 4]

这在需要对包含大量项目的 Collection 进行转换操作时特别有用:

$count = $hugeCollection
    ->lazy()
    ->where('country', 'FR')
    ->where('balance', '>', '100')
    ->count();

通过将集合转换为 LazyCollection,我们避免了分配大量额外内存。
虽然原始集合的值仍会保存在内存中,但后续的筛选操作不会。
因此,在过滤集合结果时几乎不会再占用额外的内存。

macro()

静态方法 macro 允许你在运行时向 Collection 类中添加自定义方法。
有关更多信息,请参阅 扩展集合 的相关文档。

无与伦比 翻译于 5天前

make()

静态方法 make 用于创建一个新的集合实例。
参见 创建集合 部分。

use Illuminate\Support\Collection;

$collection = Collection::make([1, 2, 3]);

map()

map 方法会遍历集合中的每个项目,并将每个值传递给给定的回调函数。
回调函数可以对项目进行修改并返回修改后的值,从而形成一个包含修改后项目的新集合:

$collection = collect([1, 2, 3, 4, 5]);

$multiplied = $collection->map(function (int $item, int $key) {
    return $item * 2;
});

$multiplied->all();

// [2, 4, 6, 8, 10]

[!警告]
与大多数其他集合方法一样,map 会返回一个新的集合实例;它不会修改被调用的原始集合。
如果你想直接转换原集合,请使用 transform 方法。

mapInto()

mapInto() 方法会遍历集合中的每个项目,并将项目的值传递给给定类的构造函数,从而创建该类的新实例:

class Currency
{
    /**
     * 创建一个新的 Currency 实例。
     */
    function __construct(
        public string $code,
    ) {}
}

$collection = collect(['USD', 'EUR', 'GBP']);

$currencies = $collection->mapInto(Currency::class);

$currencies->all();

// [Currency('USD'), Currency('EUR'), Currency('GBP')]

mapSpread()

mapSpread 方法会遍历集合中的项目,并将每个嵌套项目的值依次传入给定的闭包。
闭包可以自由修改这些值并返回结果,从而形成一个包含修改后项目的新集合:

$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunks = $collection->chunk(2);

$sequence = $chunks->mapSpread(function (int $even, int $odd) {
    return $even + $odd;
});

$sequence->all();

// [1, 5, 9, 13, 17]

mapToGroups()

mapToGroups 方法会根据给定的闭包对集合中的项目进行分组。
闭包应返回一个仅包含单个键 / 值对的关联数组,从而形成一个新的分组集合:

$collection = collect([
    [
        'name' => 'John Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Jane Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Johnny Doe',
        'department' => 'Marketing',
    ]
]);

$grouped = $collection->mapToGroups(function (array $item, int $key) {
    return [$item['department'] => $item['name']];
});

$grouped->all();

/*
    [
        'Sales' => ['John Doe', 'Jane Doe'],
        'Marketing' => ['Johnny Doe'],
    ]
*/

$grouped->get('Sales')->all();

// ['John Doe', 'Jane Doe']
无与伦比 翻译于 5天前

mapWithKeys()

mapWithKeys 方法会遍历集合,并将每个值传递给指定的回调函数。
回调函数应返回一个只包含单个键值对的关联数组:

$collection = collect([
    [
        'name' => 'John',
        'department' => 'Sales',
        'email' => 'john@example.com',
    ],
    [
        'name' => 'Jane',
        'department' => 'Marketing',
        'email' => 'jane@example.com',
    ]
]);

$keyed = $collection->mapWithKeys(function (array $item, int $key) {
    return [$item['email'] => $item['name']];
});

$keyed->all();

/*
    [
        'john@example.com' => 'John',
        'jane@example.com' => 'Jane',
    ]
*/

max()

max 方法返回指定键的最大值:

$max = collect([
    ['foo' => 10],
    ['foo' => 20]
])->max('foo');

// 20

$max = collect([1, 2, 3, 4, 5])->max();

// 5

median()

median 方法返回指定键的中位数值

$median = collect([
    ['foo' => 10],
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 40]
])->median('foo');

// 15

$median = collect([1, 1, 2, 4])->median();

// 1.5

merge()

merge 方法会将给定的数组或集合与原集合合并。
如果给定数据中的字符串键与原集合的字符串键相同,则新值会覆盖旧值:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->merge(['price' => 200, 'discount' => false]);

$merged->all();

// ['product_id' => 1, 'price' => 200, 'discount' => false]

如果给定数据的键是数字索引,则这些值会被追加到集合的末尾:

$collection = collect(['Desk', 'Chair']);

$merged = $collection->merge(['Bookcase', 'Door']);

$merged->all();

// ['Desk', 'Chair', 'Bookcase', 'Door']

mergeRecursive()

mergeRecursive 方法会递归地将给定数组或集合与原集合合并。
如果给定数据中的字符串键与原集合的键相同,则这些键的值会被合并成数组,并递归执行此操作:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->mergeRecursive([
    'product_id' => 2,
    'price' => 200,
    'discount' => false
]);

$merged->all();

// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
无与伦比 翻译于 4天前

min()

min 方法返回指定键的最小值:

$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');

// 10

$min = collect([1, 2, 3, 4, 5])->min();

// 1

mode()

mode 方法返回指定键的众数值(即出现次数最多的值):

$mode = collect([
    ['foo' => 10],
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 40]
])->mode('foo');

// [10]

$mode = collect([1, 1, 2, 4])->mode();

// [1]

$mode = collect([1, 1, 2, 2])->mode();

// [1, 2]

multiply()

multiply 方法会为集合中的所有元素创建指定数量的副本:

$users = collect([
    ['name' => 'User #1', 'email' => 'user1@example.com'],
    ['name' => 'User #2', 'email' => 'user2@example.com'],
])->multiply(3);

/*
    [
        ['name' => 'User #1', 'email' => 'user1@example.com'],
        ['name' => 'User #2', 'email' => 'user2@example.com'],
        ['name' => 'User #1', 'email' => 'user1@example.com'],
        ['name' => 'User #2', 'email' => 'user2@example.com'],
        ['name' => 'User #1', 'email' => 'user1@example.com'],
        ['name' => 'User #2', 'email' => 'user2@example.com'],
    ]
*/

nth()

nth 方法会创建一个新的集合,包含原集合中每隔 n 个元素的一个:

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

$collection->nth(4);

// ['a', 'e']

你也可以传入第二个参数来指定起始偏移量:

$collection->nth(4, 1);

// ['b', 'f']

only()

only 方法返回集合中指定键的项目:

$collection = collect([
    'product_id' => 1,
    'name' => 'Desk',
    'price' => 100,
    'discount' => false
]);

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

若要实现相反的效果,请参阅 except 方法。

[!注意]
当使用 Eloquent 集合 时,此方法的行为会有所不同。

无与伦比 翻译于 4天前

pad()

pad 方法会用指定的值填充数组,直到数组达到指定的大小。
该方法的行为与 PHP 的 array_pad 函数相同。

如果要向左填充,应指定一个负数大小。
如果给定大小的绝对值小于或等于数组的长度,则不会进行填充:

$collection = collect(['A', 'B', 'C']);

$filtered = $collection->pad(5, 0);

$filtered->all();

// ['A', 'B', 'C', 0, 0]

$filtered = $collection->pad(-5, 0);

$filtered->all();

// [0, 0, 'A', 'B', 'C']

partition()

partition 方法可以与 PHP 的数组解构结合使用,用于将满足条件的元素与不满足条件的元素分开:

$collection = collect([1, 2, 3, 4, 5, 6]);

[$underThree, $equalOrAboveThree] = $collection->partition(function (int $i) {
    return $i < 3;
});

$underThree->all();

// [1, 2]

$equalOrAboveThree->all();

// [3, 4, 5, 6]

[!注意]
当与 Eloquent 集合 一起使用时,此方法的行为会有所不同。

percentage()

percentage 方法可用于快速计算集合中满足指定条件的元素所占的百分比

$collection = collect([1, 1, 2, 2, 2, 3]);

$percentage = $collection->percentage(fn (int $value) => $value === 1);

// 33.33

默认情况下,百分比会保留两位小数。
但你可以通过传递第二个参数来自定义精度:

$percentage = $collection->percentage(fn (int $value) => $value === 1, precision: 3);

// 33.333

pipe()

pipe 方法会将集合传递给指定的闭包,并返回闭包执行的结果:

$collection = collect([1, 2, 3]);

$piped = $collection->pipe(function (Collection $collection) {
    return $collection->sum();
});

// 6
无与伦比 翻译于 4天前

pipeInto()

pipeInto 方法会创建给定类的新实例,并将当前集合传递给该类的构造函数:

class ResourceCollection
{
    /**
     * 创建一个新的 ResourceCollection 实例。
     */
    public function __construct(
        public Collection $collection,
    ) {}
}

$collection = collect([1, 2, 3]);

$resource = $collection->pipeInto(ResourceCollection::class);

$resource->collection->all();

// [1, 2, 3]

pipeThrough()

pipeThrough 方法会将集合依次传递给给定的闭包数组,并返回闭包执行后的最终结果:

use Illuminate\Support\Collection;

$collection = collect([1, 2, 3]);

$result = $collection->pipeThrough([
    function (Collection $collection) {
        return $collection->merge([4, 5]);
    },
    function (Collection $collection) {
        return $collection->sum();
    },
]);

// 15

pluck()

pluck 方法用于获取指定键对应的所有值:

$collection = collect([
    ['product_id' => 'prod-100', 'name' => 'Desk'],
    ['product_id' => 'prod-200', 'name' => 'Chair'],
]);

$plucked = $collection->pluck('name');

$plucked->all();

// ['Desk', 'Chair']

你还可以指定结果集合的键名:

$plucked = $collection->pluck('name', 'product_id');

$plucked->all();

// ['prod-100' => 'Desk', 'prod-200' => 'Chair']

pluck 方法也支持使用 “点(dot)” 语法来获取嵌套值:

$collection = collect([
    [
        'name' => 'Laracon',
        'speakers' => [
            'first_day' => ['Rosa', 'Judith'],
        ],
    ],
    [
        'name' => 'VueConf',
        'speakers' => [
            'first_day' => ['Abigail', 'Joey'],
        ],
    ],
]);

$plucked = $collection->pluck('speakers.first_day');

$plucked->all();

// [['Rosa', 'Judith'], ['Abigail', 'Joey']]

如果存在重复的键,最后一个匹配的元素将会覆盖之前的值:

$collection = collect([
    ['brand' => 'Tesla',  'color' => 'red'],
    ['brand' => 'Pagani', 'color' => 'white'],
    ['brand' => 'Tesla',  'color' => 'black'],
    ['brand' => 'Pagani', 'color' => 'orange'],
]);

$plucked = $collection->pluck('color', 'brand');

$plucked->all();

// ['Tesla' => 'black', 'Pagani' => 'orange']
无与伦比 翻译于 4天前

pop 方法会移除并返回集合中的最后一个元素
如果集合为空,则会返回 null

$collection = collect([1, 2, 3, 4, 5]);

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

你也可以向 pop 方法传入一个整数,用来移除并返回集合末尾的多个元素

$collection = collect([1, 2, 3, 4, 5]);

$collection->pop(3);

// collect([5, 4, 3])

$collection->all();

// [1, 2]

prepend()

prepend 方法会在集合的开头添加一个元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->prepend(0);

$collection->all();

// [0, 1, 2, 3, 4, 5]

你也可以传入第二个参数来指定新元素的键名:

$collection = collect(['one' => 1, 'two' => 2]);

$collection->prepend(0, 'zero');

$collection->all();

// ['zero' => 0, 'one' => 1, 'two' => 2]

pull()

pull 方法根据指定的键移除并返回集合中的一个元素

$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);

$collection->pull('name');

// 'Desk'

$collection->all();

// ['product_id' => 'prod-100']

push()

push 方法会将一个元素追加到集合的末尾

$collection = collect([1, 2, 3, 4]);

$collection->push(5);

$collection->all();

// [1, 2, 3, 4, 5]

put()

put 方法会在集合中设置指定的键和值

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

$collection->put('price', 100);

$collection->all();

// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]

random()

random 方法会从集合中随机返回一个元素

$collection = collect([1, 2, 3, 4, 5]);

$collection->random();

// 4 - (随机返回)

你也可以传入一个整数,指定要随机获取的元素数量。
当显式指定数量时,返回的总是一个新的集合:

$random = $collection->random(3);

$random->all();

// [2, 4, 5] - (retrieved randomly)
无与伦比 翻译于 4天前

如果集合中的项目数量少于请求的数量random 方法将抛出一个 InvalidArgumentException 异常。

random 方法还可以接受一个闭包(closure),该闭包会接收当前的集合实例作为参数:

use Illuminate\Support\Collection;

$random = $collection->random(fn (Collection $items) => min(10, count($items)));

$random->all();

// [1, 2, 3, 4, 5] - (随机返回)

range()

range 方法返回一个包含指定范围内整数的集合:

$collection = collect()->range(3, 6);

$collection->all();

// [3, 4, 5, 6]

reduce()

reduce 方法会将集合归约为单个值,在每次迭代中将上一次迭代的结果传递到下一次迭代中:

$collection = collect([1, 2, 3]);

$total = $collection->reduce(function (?int $carry, int $item) {
    return $carry + $item;
});

// 6

第一次迭代时,$carry 的值为 null
不过,你可以通过传递第二个参数来指定初始值:

$collection->reduce(function (int $carry, int $item) {
    return $carry + $item;
}, 4);

// 10

reduce 方法还会将数组的键名作为参数传递给回调函数:

$collection = collect([
    'usd' => 1400,
    'gbp' => 1200,
    'eur' => 1000,
]);

$ratio = [
    'usd' => 1,
    'gbp' => 1.37,
    'eur' => 1.22,
];

$collection->reduce(function (int $carry, int $value, string $key) use ($ratio) {
    return $carry + ($value * $ratio[$key]);
}, 0);

// 4264

reduceSpread()

reduceSpread 方法会将集合归约为一个值数组,并在每次迭代中将结果传递到下一次迭代中。
该方法与 reduce 类似,但它可以接收多个初始值

[$creditsRemaining, $batch] = Image::where('status', 'unprocessed')
    ->get()
    ->reduceSpread(function (int $creditsRemaining, Collection $batch, Image $image) {
        if ($creditsRemaining >= $image->creditsRequired()) {
            $batch->push($image);

            $creditsRemaining -= $image->creditsRequired();
        }

        return [$creditsRemaining, $batch];
    }, $creditsAvailable, collect());
无与伦比 翻译于 4天前

reject()

reject 方法会使用给定的闭包(closure)来过滤集合。
如果闭包返回 true,则该项会被从结果集合中移除

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->reject(function (int $value, int $key) {
    return $value > 2;
});

$filtered->all();

// [1, 2]

若要获得与 reject 相反的效果,请参阅 filter 方法。

replace()

replace 方法与 merge 方法类似;
但与 merge 不同的是,replace 除了会覆盖具有相同字符串键的项目外,
还会覆盖集合中具有相同数字键的项目:

$collection = collect(['Taylor', 'Abigail', 'James']);

$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);

$replaced->all();

// ['Taylor', 'Victoria', 'James', 'Finn']

replaceRecursive()

replaceRecursive 方法与 replace 类似,
但它会递归地进入数组,并对内部值执行相同的替换逻辑:

$collection = collect([
    'Taylor',
    'Abigail',
    [
        'James',
        'Victoria',
        'Finn'
    ]
]);

$replaced = $collection->replaceRecursive([
    'Charlie',
    2 => [1 => 'King']
]);

$replaced->all();

// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]

reverse()

reverse 方法会反转集合中项目的顺序,同时保留原始的键名

$collection = collect(['a', 'b', 'c', 'd', 'e']);

$reversed = $collection->reverse();

$reversed->all();

/*
    [
        4 => 'e',
        3 => 'd',
        2 => 'c',
        1 => 'b',
        0 => 'a',
    ]
*/

search()

search 方法在集合中查找给定的值,并在找到时返回其键。
如果未找到该项,则返回 false

$collection = collect([2, 4, 6, 8]);

$collection->search(4);

// 1

搜索默认使用宽松比较(loose comparison)
即数字字符串会被视为与相同值的整数相等。
若要使用严格比较(strict comparison)
可以将第二个参数设置为 true

collect([2, 4, 6, 8])->search('4', strict: true);

// false
无与伦比 翻译于 4天前

或者,你也可以提供你自己的闭包(closure)来查找通过给定条件测试的第一个元素:

collect([2, 4, 6, 8])->search(function (int $item, int $key) {
    return $item > 5;
});

// 2

select()

select 方法从集合中选择指定的键,类似于 SQL 的 SELECT 语句:

$users = collect([
    ['name' => 'Taylor Otwell', 'role' => 'Developer', 'status' => 'active'],
    ['name' => 'Victoria Faith', 'role' => 'Researcher', 'status' => 'active'],
]);

$users->select(['name', 'role']);

/*
    [
        ['name' => 'Taylor Otwell', 'role' => 'Developer'],
        ['name' => 'Victoria Faith', 'role' => 'Researcher'],
    ],
*/

shift()

shift 方法会移除并返回集合中的第一个元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

你可以向 shift 方法传入一个整数,以移除并返回集合开头的多个元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->shift(3);

// collect([1, 2, 3])

$collection->all();

// [4, 5]

shuffle()

shuffle 方法会随机打乱集合中的元素顺序:

$collection = collect([1, 2, 3, 4, 5]);

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (generated randomly)

skip()

skip 方法返回一个新集合,从原集合的开头移除指定数量的元素:

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$collection = $collection->skip(4);

$collection->all();

// [5, 6, 7, 8, 9, 10]

skipUntil()

skipUntil 方法会跳过集合中的元素,直到给定的回调函数返回 true
一旦回调返回 true,剩下的所有元素都会作为一个新集合返回:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipUntil(function (int $item) {
    return $item >= 3;
});

$subset->all();

// [3, 4]
无与伦比 翻译于 3天前

你也可以向 skipUntil 方法传入一个简单的值,以跳过所有元素,直到找到给定的值为止:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipUntil(3);

$subset->all();

// [3, 4]

[!警告]
如果未找到给定的值,或者回调函数从未返回 trueskipUntil 方法将返回一个空集合。

skipWhile()

skipWhile 方法会跳过集合中的元素,只要给定的回调函数返回 true
一旦回调返回 false,集合中剩余的所有元素将作为一个新集合返回:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipWhile(function (int $item) {
    return $item <= 3;
});

$subset->all();

// [4]

[!警告]
如果回调函数从未返回 falseskipWhile 方法将返回一个空集合。

slice()

slice 方法从给定的索引位置开始,返回集合的一部分(切片):

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$slice = $collection->slice(4);

$slice->all();

// [5, 6, 7, 8, 9, 10]

如果你希望限制返回切片的大小,可以将期望的大小作为第二个参数传递给该方法:

$slice = $collection->slice(4, 2);

$slice->all();

// [5, 6]

返回的切片默认会保留原始的键(key)。
如果你不希望保留原始键,可以使用 values 方法重新为它们建立索引。

sliding()

sliding 方法返回一个新的集合,其中包含表示“滑动窗口”视图的分块(chunk):

$collection = collect([1, 2, 3, 4, 5]);

$chunks = $collection->sliding(2);

$chunks->toArray();

// [[1, 2], [2, 3], [3, 4], [4, 5]]

这在与 eachSpread 方法结合使用时特别有用:

$transactions->sliding(2)->eachSpread(function (Collection $previous, Collection $current) {
    $current->total = $previous->total + $current->amount;
});
无与伦比 翻译于 3天前

你还可以选择传递第二个“步长”(step)参数,用于指定每个分块第一个元素之间的间隔距离:

$collection = collect([1, 2, 3, 4, 5]);

$chunks = $collection->sliding(3, step: 2);

$chunks->toArray();

// [[1, 2, 3], [3, 4, 5]]

sole()

sole 方法返回集合中第一个通过给定条件测试的元素,但前提是该条件只匹配一个元素:

collect([1, 2, 3, 4])->sole(function (int $value, int $key) {
    return $value === 2;
});

// 2

你也可以向 sole 方法传递一个键/值对,它将返回集合中第一个与给定键值对匹配的元素,但同样要求只有一个元素匹配:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
]);

$collection->sole('product', 'Chair');

// ['product' => 'Chair', 'price' => 100]

另外,你还可以在不传递任何参数的情况下调用 sole 方法,以在集合中只有一个元素时返回该元素:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
]);

$collection->sole();

// ['product' => 'Desk', 'price' => 200]

如果集合中没有任何元素符合 sole 方法的条件,将会抛出 \Illuminate\Collections\ItemNotFoundException 异常。
如果有多个元素符合条件,则会抛出 \Illuminate\Collections\MultipleItemsFoundException 异常。

some()

some 方法是 contains 方法的别名。

sort()

sort 方法用于对集合进行排序。
排序后的集合会保留原始的数组键,因此在以下示例中,我们使用 values 方法重置键为连续的数字索引:

$collection = collect([5, 3, 1, 2, 4]);

$sorted = $collection->sort();

$sorted->values()->all();

// [1, 2, 3, 4, 5]
无与伦比 翻译于 3天前

如果你的排序需求更加复杂,你可以向 sort 方法传递一个回调函数,以使用你自己的排序算法。
请参阅 PHP 文档中关于 uasort 的说明,集合的 sort 方法在内部正是调用了该函数。

[!注意]
如果你需要对嵌套数组或对象的集合进行排序,请参阅 sortBysortByDesc 方法。

sortBy()

sortBy 方法根据给定的键对集合进行排序。
排序后的集合会保留原始数组的键,因此在以下示例中,我们使用 values 方法重置键为连续编号的索引:

$collection = collect([
    ['name' => 'Desk', 'price' => 200],
    ['name' => 'Chair', 'price' => 100],
    ['name' => 'Bookcase', 'price' => 150],
]);

$sorted = $collection->sortBy('price');

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'price' => 100],
        ['name' => 'Bookcase', 'price' => 150],
        ['name' => 'Desk', 'price' => 200],
    ]
*/

sortBy 方法的第二个参数可以接受 排序标志(sort flags)

$collection = collect([
    ['title' => 'Item 1'],
    ['title' => 'Item 12'],
    ['title' => 'Item 3'],
]);

$sorted = $collection->sortBy('title', SORT_NATURAL);

$sorted->values()->all();

/*
    [
        ['title' => 'Item 1'],
        ['title' => 'Item 3'],
        ['title' => 'Item 12'],
    ]
*/

此外,你也可以传递你自己的闭包来决定集合值的排序方式:

$collection = collect([
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$sorted = $collection->sortBy(function (array $product, int $key) {
    return count($product['colors']);
});

$sorted->values()->all();

/*
    [
        ['name' => 'Chair', 'colors' => ['Black']],
        ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
        ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
    ]
*/
无与伦比 翻译于 3天前

如果你希望按照多个属性对集合进行排序,可以向 sortBy 方法传递一个由多个排序操作组成的数组。每个排序操作都应该是一个数组,包含你希望排序的属性名称以及排序方向:

$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
    ['name', 'asc'],
    ['age', 'desc'],
]);

$sorted->values()->all();

/*
    [
        ['name' => 'Abigail Otwell', 'age' => 32],
        ['name' => 'Abigail Otwell', 'age' => 30],
        ['name' => 'Taylor Otwell', 'age' => 36],
        ['name' => 'Taylor Otwell', 'age' => 34],
    ]
*/

当按照多个属性对集合进行排序时,你也可以提供定义每个排序操作的闭包:

$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
    fn (array $a, array $b) => $a['name'] <=> $b['name'],
    fn (array $a, array $b) => $b['age'] <=> $a['age'],
]);

$sorted->values()->all();

/*
    [
        ['name' => 'Abigail Otwell', 'age' => 32],
        ['name' => 'Abigail Otwell', 'age' => 30],
        ['name' => 'Taylor Otwell', 'age' => 36],
        ['name' => 'Taylor Otwell', 'age' => 34],
    ]
*/

sortByDesc()

此方法与 sortBy 方法具有相同的函数签名,但会以相反的顺序对集合进行排序。

sortDesc()

此方法会以与 sort 方法相反的顺序对集合进行排序:

$collection = collect([5, 3, 1, 2, 4]);

$sorted = $collection->sortDesc();

$sorted->values()->all();

// [5, 4, 3, 2, 1]

sort 不同,sortDesc 不支持传递闭包。
如果你需要使用自定义排序逻辑,请使用 sort 方法并反转你的比较结果。

无与伦比 翻译于 3天前

sortKeys()

The sortKeys method sorts the collection by the keys of the underlying associative array:

$collection = collect([
    'id' => 22345,
    'first' => 'John',
    'last' => 'Doe',
]);

$sorted = $collection->sortKeys();

$sorted->all();

/*
    [
        'first' => 'John',
        'id' => 22345,
        'last' => 'Doe',
    ]
*/

sortKeysDesc()

This method has the same signature as the sortKeys method, but will sort the collection in the opposite order.

sortKeysUsing()

The sortKeysUsing method sorts the collection by the keys of the underlying associative array using a callback:

$collection = collect([
    'ID' => 22345,
    'first' => 'John',
    'last' => 'Doe',
]);

$sorted = $collection->sortKeysUsing('strnatcasecmp');

$sorted->all();

/*
    [
        'first' => 'John',
        'ID' => 22345,
        'last' => 'Doe',
    ]
*/

The callback must be a comparison function that returns an integer less than, equal to, or greater than zero. For more information, refer to the PHP documentation on uksort, which is the PHP function that sortKeysUsing method utilizes internally.

splice()

The splice method removes and returns a slice of items starting at the specified index:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2);

$chunk->all();

// [3, 4, 5]

$collection->all();

// [1, 2]

You may pass a second argument to limit the size of the resulting collection:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2, 1);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 4, 5]

In addition, you may pass a third argument containing the new items to replace the items removed from the collection:

$collection = collect([1, 2, 3, 4, 5]);

$chunk = $collection->splice(2, 1, [10, 11]);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 10, 11, 4, 5]

split()

The split method breaks a collection into the given number of groups:

$collection = collect([1, 2, 3, 4, 5]);

$groups = $collection->split(3);

$groups->all();

// [[1, 2], [3, 4], [5]]

splitIn()

The splitIn method breaks a collection into the given number of groups, filling non-terminal groups completely before allocating the remainder to the final group:

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

$groups = $collection->splitIn(3);

$groups->all();

// [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

sum()

The sum method returns the sum of all items in the collection:

collect([1, 2, 3, 4, 5])->sum();

// 15

If the collection contains nested arrays or objects, you should pass a key that will be used to determine which values to sum:

$collection = collect([
    ['name' => 'JavaScript: The Good Parts', 'pages' => 176],
    ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);

$collection->sum('pages');

// 1272

In addition, you may pass your own closure to determine which values of the collection to sum:

$collection = collect([
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$collection->sum(function (array $product) {
    return count($product['colors']);
});

// 6

take()

The take method returns a new collection with the specified number of items:

$collection = collect([0, 1, 2, 3, 4, 5]);

$chunk = $collection->take(3);

$chunk->all();

// [0, 1, 2]

You may also pass a negative integer to take the specified number of items from the end of the collection:

$collection = collect([0, 1, 2, 3, 4, 5]);

$chunk = $collection->take(-2);

$chunk->all();

// [4, 5]

takeUntil()

The takeUntil method returns items in the collection until the given callback returns true:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->takeUntil(function (int $item) {
    return $item >= 3;
});

$subset->all();

// [1, 2]

You may also pass a simple value to the takeUntil method to get the items until the given value is found:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->takeUntil(3);

$subset->all();

// [1, 2]

[!WARNING]
If the given value is not found or the callback never returns true, the takeUntil method will return all items in the collection.

takeWhile()

The takeWhile method returns items in the collection until the given callback returns false:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->takeWhile(function (int $item) {
    return $item < 3;
});

$subset->all();

// [1, 2]

[!WARNING]
If the callback never returns false, the takeWhile method will return all items in the collection.

tap()

The tap method passes the collection to the given callback, allowing you to "tap" into the collection at a specific point and do something with the items while not affecting the collection itself. The collection is then returned by the tap method:

collect([2, 4, 3, 1, 5])
    ->sort()
    ->tap(function (Collection $collection) {
        Log::debug('Values after sorting', $collection->values()->all());
    })
    ->shift();

// 1

times()

The static times method creates a new collection by invoking the given closure a specified number of times:

$collection = Collection::times(10, function (int $number) {
    return $number * 9;
});

$collection->all();

// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

toArray()

The toArray method converts the collection into a plain PHP array. If the collection's values are Eloquent models, the models will also be converted to arrays:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toArray();

/*
    [
        ['name' => 'Desk', 'price' => 200],
    ]
*/

[!WARNING]
toArray also converts all of the collection's nested objects that are an instance of Arrayable to an array. If you want to get the raw array underlying the collection, use the all method instead.

toJson()

The toJson method converts the collection into a JSON serialized string:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toJson();

// '{"name":"Desk", "price":200}'

transform()

The transform method iterates over the collection and calls the given callback with each item in the collection. The items in the collection will be replaced by the values returned by the callback:

$collection = collect([1, 2, 3, 4, 5]);

$collection->transform(function (int $item, int $key) {
    return $item * 2;
});

$collection->all();

// [2, 4, 6, 8, 10]

[!WARNING]
Unlike most other collection methods, transform modifies the collection itself. If you wish to create a new collection instead, use the map method.

undot()

The undot method expands a single-dimensional collection that uses "dot" notation into a multi-dimensional collection:

$person = collect([
    'name.first_name' => 'Marie',
    'name.last_name' => 'Valentine',
    'address.line_1' => '2992 Eagle Drive',
    'address.line_2' => '',
    'address.suburb' => 'Detroit',
    'address.state' => 'MI',
    'address.postcode' => '48219'
]);

$person = $person->undot();

$person->toArray();

/*
    [
        "name" => [
            "first_name" => "Marie",
            "last_name" => "Valentine",
        ],
        "address" => [
            "line_1" => "2992 Eagle Drive",
            "line_2" => "",
            "suburb" => "Detroit",
            "state" => "MI",
            "postcode" => "48219",
        ],
    ]
*/

union()

The union method adds the given array to the collection. If the given array contains keys that are already in the original collection, the original collection's values will be preferred:

$collection = collect([1 => ['a'], 2 => ['b']]);

$union = $collection->union([3 => ['c'], 1 => ['d']]);

$union->all();

// [1 => ['a'], 2 => ['b'], 3 => ['c']]

unique()

The unique method returns all of the unique items in the collection. The returned collection keeps the original array keys, so in the following example we will use the values method to reset the keys to consecutively numbered indexes:

$collection = collect([1, 1, 2, 2, 3, 4, 2]);

$unique = $collection->unique();

$unique->values()->all();

// [1, 2, 3, 4]

When dealing with nested arrays or objects, you may specify the key used to determine uniqueness:

$collection = collect([
    ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
    ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
    ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);

$unique = $collection->unique('brand');

$unique->values()->all();

/*
    [
        ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
        ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
    ]
*/

Finally, you may also pass your own closure to the unique method to specify which value should determine an item's uniqueness:

$unique = $collection->unique(function (array $item) {
    return $item['brand'].$item['type'];
});

$unique->values()->all();

/*
    [
        ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
        ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
        ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
        ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
    ]
*/

The unique method uses "loose" comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the uniqueStrict method to filter using "strict" comparisons.

[!NOTE]
This method's behavior is modified when using Eloquent Collections.

uniqueStrict()

This method has the same signature as the unique method; however, all values are compared using "strict" comparisons.

unless()

The unless method will execute the given callback unless the first argument given to the method evaluates to true. The collection instance and the first argument given to the unless method will be provided to the closure:

$collection = collect([1, 2, 3]);

$collection->unless(true, function (Collection $collection, bool $value) {
    return $collection->push(4);
});

$collection->unless(false, function (Collection $collection, bool $value) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

A second callback may be passed to the unless method. The second callback will be executed when the first argument given to the unless method evaluates to true:

$collection = collect([1, 2, 3]);

$collection->unless(true, function (Collection $collection, bool $value) {
    return $collection->push(4);
}, function (Collection $collection, bool $value) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

For the inverse of unless, see the when method.

unlessEmpty()

Alias for the whenNotEmpty method.

unlessNotEmpty()

Alias for the whenEmpty method.

unwrap()

The static unwrap method returns the collection's underlying items from the given value when applicable:

Collection::unwrap(collect('John Doe'));

// ['John Doe']

Collection::unwrap(['John Doe']);

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

value()

The value method retrieves a given value from the first element of the collection:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Speaker', 'price' => 400],
]);

$value = $collection->value('price');

// 200

values()

The values method returns a new collection with the keys reset to consecutive integers:

$collection = collect([
    10 => ['product' => 'Desk', 'price' => 200],
    11 => ['product' => 'Desk', 'price' => 200],
]);

$values = $collection->values();

$values->all();

/*
    [
        0 => ['product' => 'Desk', 'price' => 200],
        1 => ['product' => 'Desk', 'price' => 200],
    ]
*/

when()

The when method will execute the given callback when the first argument given to the method evaluates to true. The collection instance and the first argument given to the when method will be provided to the closure:

$collection = collect([1, 2, 3]);

$collection->when(true, function (Collection $collection, bool $value) {
    return $collection->push(4);
});

$collection->when(false, function (Collection $collection, bool $value) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 4]

A second callback may be passed to the when method. The second callback will be executed when the first argument given to the when method evaluates to false:

$collection = collect([1, 2, 3]);

$collection->when(false, function (Collection $collection, bool $value) {
    return $collection->push(4);
}, function (Collection $collection, bool $value) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

For the inverse of when, see the unless method.

whenEmpty()

The whenEmpty method will execute the given callback when the collection is empty:

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// ['Michael', 'Tom']

$collection = collect();

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// ['Adam']

A second closure may be passed to the whenEmpty method that will be executed when the collection is not empty:

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
}, function (Collection $collection) {
    return $collection->push('Taylor');
});

$collection->all();

// ['Michael', 'Tom', 'Taylor']

For the inverse of whenEmpty, see the whenNotEmpty method.

whenNotEmpty()

The whenNotEmpty method will execute the given callback when the collection is not empty:

$collection = collect(['Michael', 'Tom']);

$collection->whenNotEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// ['Michael', 'Tom', 'Adam']

$collection = collect();

$collection->whenNotEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// []

A second closure may be passed to the whenNotEmpty method that will be executed when the collection is empty:

$collection = collect();

$collection->whenNotEmpty(function (Collection $collection) {
    return $collection->push('Adam');
}, function (Collection $collection) {
    return $collection->push('Taylor');
});

$collection->all();

// ['Taylor']

For the inverse of whenNotEmpty, see the whenEmpty method.

where()

The where method filters the collection by a given key / value pair:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->where('price', 100);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

The where method uses "loose" comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereStrict method to filter using "strict" comparisons.

Optionally, you may pass a comparison operator as the second parameter. Supported operators are: '===', '!==', '!=', '==', '=', '<>', '>', '<', '>=', and '<=':

$collection = collect([
    ['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
    ['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
    ['name' => 'Sue', 'deleted_at' => null],
]);

$filtered = $collection->where('deleted_at', '!=', null);

$filtered->all();

/*
    [
        ['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
        ['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
    ]
*/

whereStrict()

This method has the same signature as the where method; however, all values are compared using "strict" comparisons.

whereBetween()

The whereBetween method filters the collection by determining if a specified item value is within a given range:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 80],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Pencil', 'price' => 30],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereBetween('price', [100, 200]);

$filtered->all();

/*
    [
        ['product' => 'Desk', 'price' => 200],
        ['product' => 'Bookcase', 'price' => 150],
        ['product' => 'Door', 'price' => 100],
    ]
*/

whereIn()

The whereIn method removes elements from the collection that do not have a specified item value that is contained within the given array:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Desk', 'price' => 200],
        ['product' => 'Bookcase', 'price' => 150],
    ]
*/

The whereIn method uses "loose" comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereInStrict method to filter using "strict" comparisons.

whereInStrict()

This method has the same signature as the whereIn method; however, all values are compared using "strict" comparisons.

whereInstanceOf()

The whereInstanceOf method filters the collection by a given class type:

use App\Models\User;
use App\Models\Post;

$collection = collect([
    new User,
    new User,
    new Post,
]);

$filtered = $collection->whereInstanceOf(User::class);

$filtered->all();

// [App\Models\User, App\Models\User]

whereNotBetween()

The whereNotBetween method filters the collection by determining if a specified item value is outside of a given range:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 80],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Pencil', 'price' => 30],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereNotBetween('price', [100, 200]);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 80],
        ['product' => 'Pencil', 'price' => 30],
    ]
*/

whereNotIn()

The whereNotIn method removes elements from the collection that have a specified item value that is contained within the given array:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
    ['product' => 'Bookcase', 'price' => 150],
    ['product' => 'Door', 'price' => 100],
]);

$filtered = $collection->whereNotIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

The whereNotIn method uses "loose" comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value. Use the whereNotInStrict method to filter using "strict" comparisons.

whereNotInStrict()

This method has the same signature as the whereNotIn method; however, all values are compared using "strict" comparisons.

whereNotNull()

The whereNotNull method returns items from the collection where the given key is not null:

$collection = collect([
    ['name' => 'Desk'],
    ['name' => null],
    ['name' => 'Bookcase'],
]);

$filtered = $collection->whereNotNull('name');

$filtered->all();

/*
    [
        ['name' => 'Desk'],
        ['name' => 'Bookcase'],
    ]
*/

whereNull()

The whereNull method returns items from the collection where the given key is null:

$collection = collect([
    ['name' => 'Desk'],
    ['name' => null],
    ['name' => 'Bookcase'],
]);

$filtered = $collection->whereNull('name');

$filtered->all();

/*
    [
        ['name' => null],
    ]
*/

wrap()

The static wrap method wraps the given value in a collection when applicable:

use Illuminate\Support\Collection;

$collection = Collection::wrap('John Doe');

$collection->all();

// ['John Doe']

$collection = Collection::wrap(['John Doe']);

$collection->all();

// ['John Doe']

$collection = Collection::wrap(collect('John Doe'));

$collection->all();

// ['John Doe']

zip()

The zip method merges together the values of the given array with the values of the original collection at their corresponding index:

$collection = collect(['Chair', 'Desk']);

$zipped = $collection->zip([100, 200]);

$zipped->all();

// [['Chair', 100], ['Desk', 200]]

Higher Order Messages

Collections also provide support for "higher order messages", which are short-cuts for performing common actions on collections. The collection methods that provide higher order messages are: average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, and unique.

Each higher order message can be accessed as a dynamic property on a collection instance. For instance, let's use the each higher order message to call a method on each object within a collection:

use App\Models\User;

$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

Likewise, we can use the sum higher order message to gather the total number of "votes" for a collection of users:

$users = User::where('group', 'Development')->get();

return $users->sum->votes;

Lazy Collections

Introduction

[!WARNING]
Before learning more about Laravel's lazy collections, take some time to familiarize yourself with PHP generators.

To supplement the already powerful Collection class, the LazyCollection class leverages PHP's generators to allow you to work with very large datasets while keeping memory usage low.

For example, imagine your application needs to process a multi-gigabyte log file while taking advantage of Laravel's collection methods to parse the logs. Instead of reading the entire file into memory at once, lazy collections may be used to keep only a small part of the file in memory at a given time:

use App\Models\LogEntry;
use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
    $handle = fopen('log.txt', 'r');

    while (($line = fgets($handle)) !== false) {
        yield $line;
    }

    fclose($handle);
})->chunk(4)->map(function (array $lines) {
    return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
    // Process the log entry...
});

Or, imagine you need to iterate through 10,000 Eloquent models. When using traditional Laravel collections, all 10,000 Eloquent models must be loaded into memory at the same time:

use App\Models\User;

$users = User::all()->filter(function (User $user) {
    return $user->id > 500;
});

However, the query builder's cursor method returns a LazyCollection instance. This allows you to still only run a single query against the database but also only keep one Eloquent model loaded in memory at a time. In this example, the filter callback is not executed until we actually iterate over each user individually, allowing for a drastic reduction in memory usage:

use App\Models\User;

$users = User::cursor()->filter(function (User $user) {
    return $user->id > 500;
});

foreach ($users as $user) {
    echo $user->id;
}

Creating Lazy Collections

To create a lazy collection instance, you should pass a PHP generator function to the collection's make method:

use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
    $handle = fopen('log.txt', 'r');

    while (($line = fgets($handle)) !== false) {
        yield $line;
    }

    fclose($handle);
});

The Enumerable Contract

Almost all methods available on the Collection class are also available on the LazyCollection class. Both of these classes implement the Illuminate\Support\Enumerable contract, which defines the following methods:

[!WARNING]
Methods that mutate the collection (such as shift, pop, prepend etc.) are not available on the LazyCollection class.

Lazy Collection Methods

In addition to the methods defined in the Enumerable contract, the LazyCollection class contains the following methods:

takeUntilTimeout()

The takeUntilTimeout method returns a new lazy collection that will enumerate values until the specified time. After that time, the collection will then stop enumerating:

$lazyCollection = LazyCollection::times(INF)
    ->takeUntilTimeout(now()->addMinute());

$lazyCollection->each(function (int $number) {
    dump($number);

    sleep(1);
});

// 1
// 2
// ...
// 58
// 59

To illustrate the usage of this method, imagine an application that submits invoices from the database using a cursor. You could define a scheduled task that runs every 15 minutes and only processes invoices for a maximum of 14 minutes:

use App\Models\Invoice;
use Illuminate\Support\Carbon;

Invoice::pending()->cursor()
    ->takeUntilTimeout(
        Carbon::createFromTimestamp(LARAVEL_START)->add(14, 'minutes')
    )
    ->each(fn (Invoice $invoice) => $invoice->submit());

tapEach()

While the each method calls the given callback for each item in the collection right away, the tapEach method only calls the given callback as the items are being pulled out of the list one by one:

// Nothing has been dumped so far...
$lazyCollection = LazyCollection::times(INF)->tapEach(function (int $value) {
    dump($value);
});

// Three items are dumped...
$array = $lazyCollection->take(3)->all();

// 1
// 2
// 3

throttle()

The throttle method will throttle the lazy collection such that each value is returned after the specified number of seconds. This method is especially useful for situations where you may be interacting with external APIs that rate limit incoming requests:

use App\Models\User;

User::where('vip', true)
    ->cursor()
    ->throttle(seconds: 1)
    ->each(function (User $user) {
        // Call external API...
    });

remember()

remember 方法返回一个新的惰性集合,这个集合已经记住(缓存)已枚举的所有值,当再次枚举该集合时不会获取它们:

// 没执行任何查询
$users = User::cursor()->remember();

// 执行了查询操作
// 并且前 5 个用户数据已经在数据库中查询完成
$users->take(5)->all();

// 前 5 个用户数据从缓存中获取
// 剩余的(15 个)用户数据从数据库中查询
$users->take(20)->all();
dkp 翻译于 3个月前

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~