集合 (Collections)
简介
Illuminate\Support\Collection 类为处理数据数组提供了流畅、便捷的包装器。例如,请看以下代码。我们将使用 collect 辅助函数从数组创建一个新的集合实例,对每个元素运行 strtoupper 函数,然后删除所有空元素:
1$collection = collect(['Taylor', 'Abigail', null])->map(function (?string $name) {2 return strtoupper($name);3})->reject(function (string $name) {4 return empty($name);5});
如你所见,Collection 类允许你链式调用其方法,从而对底层数组执行流畅的映射和归约操作。通常情况下,集合是不可变的,这意味着每个 Collection 方法都会返回一个全新的 Collection 实例。
创建集合
如上所述,collect 辅助函数会针对给定数组返回一个新的 Illuminate\Support\Collection 实例。因此,创建集合非常简单:
1$collection = collect([1, 2, 3]);
你也可以使用 make 和 fromJson 方法来创建集合。
Eloquent 查询的结果始终以 Collection 实例形式返回。
扩展集合
集合支持“宏”(macroable),这允许你在运行时向 Collection 类添加额外的方法。Illuminate\Support\Collection 类的 macro 方法接受一个闭包,当你的宏被调用时,该闭包就会执行。宏闭包可以通过 $this 访问集合的其他方法,就像它是集合类的真实方法一样。例如,以下代码为 Collection 类添加了一个 toUpper 方法:
1use Illuminate\Support\Collection; 2use Illuminate\Support\Str; 3 4Collection::macro('toUpper', function () { 5 return $this->map(function (string $value) { 6 return Str::upper($value); 7 }); 8}); 9 10$collection = collect(['first', 'second']);11 12$upper = $collection->toUpper();13 14// ['FIRST', 'SECOND']
通常,你应该在 服务提供者 的 boot 方法中声明集合宏。
宏参数
如有必要,你可以定义接受额外参数的宏:
1use Illuminate\Support\Collection; 2use Illuminate\Support\Facades\Lang; 3 4Collection::macro('toLocale', function (string $locale) { 5 return $this->map(function (string $value) use ($locale) { 6 return Lang::get($value, [], $locale); 7 }); 8}); 9 10$collection = collect(['first', 'second']);11 12$translated = $collection->toLocale('es');13 14// ['primero', 'segundo'];
可用方法
在本章后续的集合文档中,我们将讨论 Collection 类可用的每种方法。请记住,所有这些方法都可以链式调用,以流畅地操作底层数组。此外,几乎每个方法都会返回一个新的 Collection 实例,让你在必要时可以保留集合的原始副本。
after all average avg before chunk chunkWhile collapse collapseWithKeys collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffAssocUsing diffKeys doesntContain doesntContainStrict dot dump duplicates duplicatesStrict each eachSpread ensure every except filter first firstOrFail firstWhere flatMap flatten flip forget forPage fromJson get groupBy has hasAny hasMany hasSole implode intersect intersectUsing intersectAssoc intersectAssocUsing intersectByKeys isEmpty isNotEmpty join keyBy keys last lazy macro make map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode multiply nth only pad partition percentage pipe pipeInto pipeThrough pluck pop prepend pull push put random range reduce reduceSpread reject replace replaceRecursive reverse search select shift shuffle skip skipUntil skipWhile slice sliding sole some sort sortBy sortByDesc sortDesc sortKeys sortKeysDesc sortKeysUsing splice split splitIn sum take takeUntil takeWhile tap times toArray toJson toPrettyJson transform undot union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap value values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict whereNotNull whereNull wrap zip
方法列表
after()
after 方法返回给定项目之后的项目。如果未找到给定项目或该项目是最后一个,则返回 null。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->after(3);4 5// 46 7$collection->after(5);8 9// null
此方法使用“松散”比较来搜索给定项目,这意味着包含整数值的字符串将被视为等于相同值的整数。要使用“严格”比较,你可以向该方法提供 strict 参数。
1collect([2, 4, 6, 8])->after('4', strict: true);2 3// null
或者,你可以提供自己的闭包来搜索通过给定真值测试的第一个项目。
1collect([2, 4, 6, 8])->after(function (int $item, int $key) {2 return $item > 5;3});4 5// 8
all()
all 方法返回集合所代表的底层数组。
1collect([1, 2, 3])->all();2 3// [1, 2, 3]
average()
avg 方法的别名。
avg()
avg 方法返回给定键的 平均值。
1$average = collect([ 2 ['foo' => 10], 3 ['foo' => 10], 4 ['foo' => 20], 5 ['foo' => 40] 6])->avg('foo'); 7 8// 20 9 10$average = collect([1, 1, 2, 4])->avg();11 12// 2
before()
before 方法与 after 方法相反。它返回给定项目之前的项目。如果未找到给定项目或该项目是第一个,则返回 null。
1$collection = collect([1, 2, 3, 4, 5]); 2 3$collection->before(3); 4 5// 2 6 7$collection->before(1); 8 9// null10 11collect([2, 4, 6, 8])->before('4', strict: true);12 13// null14 15collect([2, 4, 6, 8])->before(function (int $item, int $key) {16 return $item > 5;17});18 19// 4
chunk()
chunk 方法将集合拆分为多个给定大小的较小集合。
1$collection = collect([1, 2, 3, 4, 5, 6, 7]);2 3$chunks = $collection->chunk(4);4 5$chunks->all();6 7// [[1, 2, 3, 4], [5, 6, 7]]
此方法在 视图 中处理网格系统(如 Bootstrap)时特别有用。例如,假设你有一个想要在网格中显示的 Eloquent 模型集合。
1@foreach ($products->chunk(3) as $chunk)2 <div class="row">3 @foreach ($chunk as $product)4 <div class="col-xs-4">{{ $product->name }}</div>5 @endforeach6 </div>7@endforeach
chunkWhile()
chunkWhile 方法根据给定回调的评估结果将集合拆分为多个较小的集合。传递给闭包的 $chunk 变量可用于检查前一个元素。
1$collection = collect(str_split('AABBCCCD'));2 3$chunks = $collection->chunkWhile(function (string $value, int $key, Collection $chunk) {4 return $value === $chunk->last();5});6 7$chunks->all();8 9// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]
collapse()
collapse 方法将集合的数组或集合折叠为单个扁平的集合。
1$collection = collect([ 2 [1, 2, 3], 3 [4, 5, 6], 4 [7, 8, 9], 5]); 6 7$collapsed = $collection->collapse(); 8 9$collapsed->all();10 11// [1, 2, 3, 4, 5, 6, 7, 8, 9]
collapseWithKeys()
collapseWithKeys 方法将数组或集合的集合展平为单个集合,并保留原始键。如果集合已经扁平,它将返回一个空集合。
1$collection = collect([ 2 ['first' => collect([1, 2, 3])], 3 ['second' => [4, 5, 6]], 4 ['third' => collect([7, 8, 9])] 5]); 6 7$collapsed = $collection->collapseWithKeys(); 8 9$collapsed->all();10 11// [12// 'first' => [1, 2, 3],13// 'second' => [4, 5, 6],14// 'third' => [7, 8, 9],15// ]
collect()
collect 方法返回一个包含当前集合中项目的新 Collection 实例。
1$collectionA = collect([1, 2, 3]);2 3$collectionB = $collectionA->collect();4 5$collectionB->all();6 7// [1, 2, 3]
collect 方法主要用于将 惰性集合 转换为标准的 Collection 实例。
1$lazyCollection = LazyCollection::make(function () { 2 yield 1; 3 yield 2; 4 yield 3; 5}); 6 7$collection = $lazyCollection->collect(); 8 9$collection::class;10 11// 'Illuminate\Support\Collection'12 13$collection->all();14 15// [1, 2, 3]
当你拥有一个 Enumerable 实例但需要非惰性集合实例时,collect() 方法特别有用。由于 collect() 是 Enumerable 契约的一部分,你可以放心地使用它来获取 Collection 实例。
combine()
combine 方法将集合的值作为键,与另一个数组或集合的值相结合。
1$collection = collect(['name', 'age']);2 3$combined = $collection->combine(['George', 29]);4 5$combined->all();6 7// ['name' => 'George', 'age' => 29]
concat()
concat 方法将给定数组或集合的值追加到另一个集合的末尾。
1$collection = collect(['John Doe']);2 3$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);4 5$concatenated->all();6 7// ['John Doe', 'Jane Doe', 'Johnny Doe']
concat 方法会为连接到原始集合的项目重新索引数字键。若要在关联集合中维护键,请参阅 merge 方法。
contains()
contains 方法确定集合是否包含给定项目。你可以向 contains 方法传递一个闭包,以确定集合中是否存在匹配给定真值测试的元素。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->contains(function (int $value, int $key) {4 return $value > 5;5});6 7// false
或者,你可以向 contains 方法传递一个字符串,以确定集合是否包含给定的项目值。
1$collection = collect(['name' => 'Desk', 'price' => 100]);2 3$collection->contains('Desk');4 5// true6 7$collection->contains('New York');8 9// false
你还可以向 contains 方法传递键/值对,它将确定集合中是否存在给定的对。
1$collection = collect([2 ['product' => 'Desk', 'price' => 200],3 ['product' => 'Chair', 'price' => 100],4]);5 6$collection->contains('product', 'Bookcase');7 8// false
contains 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 containsStrict 方法进行“严格”比较过滤。
关于 contains 的反向操作,请参阅 doesntContain 方法。
containsStrict()
此方法具有与 contains 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
使用 Eloquent 集合 时,此方法的行为会发生改变。
count()
count 方法返回集合中项目的总数。
1$collection = collect([1, 2, 3, 4]);2 3$collection->count();4 5// 4
countBy()
countBy 方法计算集合中值的出现次数。默认情况下,该方法计算每个元素出现的次数,允许你计算集合中某些“类型”元素的数量。
1$collection = collect([1, 2, 2, 2, 3]);2 3$counted = $collection->countBy();4 5$counted->all();6 7// [1 => 1, 2 => 3, 3 => 1]
你可以向 countBy 方法传递一个闭包,以通过自定义值计算所有项目。
2 3$counted = $collection->countBy(function (string $email) {4 return substr(strrchr($email, '@'), 1);5});6 7$counted->all();8 9// ['gmail.com' => 2, 'yahoo.com' => 1]
crossJoin()
crossJoin 方法在给定数组或集合之间对集合的值进行交叉连接,返回包含所有可能排列的笛卡尔积。
1$collection = collect([1, 2]); 2 3$matrix = $collection->crossJoin(['a', 'b']); 4 5$matrix->all(); 6 7/* 8 [ 9 [1, 'a'],10 [1, 'b'],11 [2, 'a'],12 [2, 'b'],13 ]14*/15 16$collection = collect([1, 2]);17 18$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);19 20$matrix->all();21 22/*23 [24 [1, 'a', 'I'],25 [1, 'a', 'II'],26 [1, 'b', 'I'],27 [1, 'b', 'II'],28 [2, 'a', 'I'],29 [2, 'a', 'II'],30 [2, 'b', 'I'],31 [2, 'b', 'II'],32 ]33*/
dd()
dd 方法打印集合的项目并结束脚本执行。
1$collection = collect(['John Doe', 'Jane Doe']); 2 3$collection->dd(); 4 5/* 6 array:2 [ 7 0 => "John Doe" 8 1 => "Jane Doe" 9 ]10*/
如果你不想停止执行脚本,请改用 dump 方法。
diff()
diff 方法根据值将集合与另一个集合或普通 PHP array 进行比较。此方法将返回存在于原始集合中但不存在于给定集合中的值。
1$collection = collect([1, 2, 3, 4, 5]);2 3$diff = $collection->diff([2, 4, 6, 8]);4 5$diff->all();6 7// [1, 3, 5]
使用 Eloquent 集合 时,此方法的行为会发生改变。
diffAssoc()
diffAssoc 方法根据键和值将集合与另一个集合或普通 PHP array 进行比较。此方法将返回存在于原始集合中但不存在于给定集合中的键/值对。
1$collection = collect([ 2 'color' => 'orange', 3 'type' => 'fruit', 4 'remain' => 6, 5]); 6 7$diff = $collection->diffAssoc([ 8 'color' => 'yellow', 9 'type' => 'fruit',10 'remain' => 3,11 'used' => 6,12]);13 14$diff->all();15 16// ['color' => 'orange', 'remain' => 6]
diffAssocUsing()
与 diffAssoc 不同,diffAssocUsing 接受用户提供的回调函数用于索引比较。
1$collection = collect([ 2 'color' => 'orange', 3 'type' => 'fruit', 4 'remain' => 6, 5]); 6 7$diff = $collection->diffAssocUsing([ 8 'Color' => 'yellow', 9 'Type' => 'fruit',10 'Remain' => 3,11], 'strnatcasecmp');12 13$diff->all();14 15// ['color' => 'orange', 'remain' => 6]
回调必须是一个比较函数,返回小于、等于或大于零的整数。有关更多信息,请参阅 PHP 关于 array_diff_uassoc 的文档,这是 diffAssocUsing 方法内部调用的 PHP 函数。
diffKeys()
diffKeys 方法根据键将集合与另一个集合或普通 PHP array 进行比较。此方法将返回存在于原始集合中但不存在于给定集合中的键/值对。
1$collection = collect([ 2 'one' => 10, 3 'two' => 20, 4 'three' => 30, 5 'four' => 40, 6 'five' => 50, 7]); 8 9$diff = $collection->diffKeys([10 'two' => 2,11 'four' => 4,12 'six' => 6,13 'eight' => 8,14]);15 16$diff->all();17 18// ['one' => 10, 'three' => 30, 'five' => 50]
doesntContain()
doesntContain 方法确定集合是否不包含给定项目。你可以向 doesntContain 方法传递一个闭包,以确定集合中是否不存在匹配给定真值测试的元素。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->doesntContain(function (int $value, int $key) {4 return $value < 5;5});6 7// false
或者,你可以向 doesntContain 方法传递一个字符串,以确定集合是否不包含给定的项目值。
1$collection = collect(['name' => 'Desk', 'price' => 100]);2 3$collection->doesntContain('Table');4 5// true6 7$collection->doesntContain('Desk');8 9// false
你还可以向 doesntContain 方法传递键/值对,它将确定集合中是否不存在给定的对。
1$collection = collect([2 ['product' => 'Desk', 'price' => 200],3 ['product' => 'Chair', 'price' => 100],4]);5 6$collection->doesntContain('product', 'Bookcase');7 8// true
doesntContain 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。
doesntContainStrict()
此方法具有与 doesntContain 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
dot()
dot 方法将多维集合展平为单层集合,并使用“点”符号来表示深度。
1$collection = collect(['products' => ['desk' => ['price' => 100]]]);2 3$flattened = $collection->dot();4 5$flattened->all();6 7// ['products.desk.price' => 100]
dump()
dump 方法打印集合的项目。
1$collection = collect(['John Doe', 'Jane Doe']); 2 3$collection->dump(); 4 5/* 6 array:2 [ 7 0 => "John Doe" 8 1 => "Jane Doe" 9 ]10*/
如果你想在打印集合后停止执行脚本,请改用 dd 方法。
duplicates()
duplicates 方法检索并返回集合中的重复值。
1$collection = collect(['a', 'b', 'a', 'c', 'b']);2 3$collection->duplicates();4 5// [2 => 'a', 4 => 'b']
如果集合包含数组或对象,你可以传递要检查重复值的属性键。
1$employees = collect([5]);6 7$employees->duplicates('position');8 9// [2 => 'Developer']
duplicatesStrict()
此方法具有与 duplicates 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
each()
each 方法迭代集合中的项目,并将每个项目传递给闭包。
1$collection = collect([1, 2, 3, 4]);2 3$collection->each(function (int $item, int $key) {4 // ...5});
如果你想停止迭代项目,可以从闭包中返回 false。
1$collection->each(function (int $item, int $key) {2 if (/* condition */) {3 return false;4 }5});
eachSpread()
eachSpread 方法迭代集合中的项目,并将每个嵌套项目的值传递给给定的回调。
1$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);2 3$collection->eachSpread(function (string $name, int $age) {4 // ...5});
你可以通过从回调中返回 false 来停止迭代项目。
1$collection->eachSpread(function (string $name, int $age) {2 return false;3});
ensure()
ensure 方法可用于验证集合的所有元素是否属于给定类型或类型列表。否则,将抛出 UnexpectedValueException。
1return $collection->ensure(User::class);2 3return $collection->ensure([User::class, Customer::class]);
也可以指定诸如 string、int、float、bool 和 array 等原始类型。
1return $collection->ensure('int');
ensure 方法不能保证以后不会向集合中添加其他类型的元素。
every()
every 方法可用于验证集合的所有元素是否通过给定的真值测试。
1collect([1, 2, 3, 4])->every(function (int $value, int $key) {2 return $value > 2;3});4 5// false
如果集合为空,every 方法将返回 true。
1$collection = collect([]);2 3$collection->every(function (int $value, int $key) {4 return $value > 2;5});6 7// true
except()
except 方法返回集合中除指定键之外的所有项目。
1$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);2 3$filtered = $collection->except(['price', 'discount']);4 5$filtered->all();6 7// ['product_id' => 1]
关于 except 的反向操作,请参阅 only 方法。
使用 Eloquent 集合 时,此方法的行为会发生改变。
filter()
filter 方法使用给定的回调过滤集合,仅保留通过给定真值测试的项目。
1$collection = collect([1, 2, 3, 4]);2 3$filtered = $collection->filter(function (int $value, int $key) {4 return $value > 2;5});6 7$filtered->all();8 9// [3, 4]
如果没有提供回调,集合中所有等效于 false 的条目将被删除。
1$collection = collect([1, 2, 3, null, false, '', 0, []]);2 3$collection->filter()->all();4 5// [1, 2, 3]
关于 filter 的反向操作,请参阅 reject 方法。
first()
first 方法返回集合中通过给定真值测试的第一个元素。
1collect([1, 2, 3, 4])->first(function (int $value, int $key) {2 return $value > 2;3});4 5// 3
你也可以在不带参数的情况下调用 first 方法来获取集合中的第一个元素。如果集合为空,则返回 null。
1collect([1, 2, 3, 4])->first();2 3// 1
firstOrFail()
firstOrFail 方法与 first 方法相同;但是,如果没有找到结果,将抛出 Illuminate\Support\ItemNotFoundException 异常。
1collect([1, 2, 3, 4])->firstOrFail(function (int $value, int $key) {2 return $value > 5;3});4 5// Throws ItemNotFoundException...
你也可以在不带参数的情况下调用 firstOrFail 方法来获取集合中的第一个元素。如果集合为空,将抛出 Illuminate\Support\ItemNotFoundException 异常。
1collect([])->firstOrFail();2 3// Throws ItemNotFoundException...
firstWhere()
firstWhere 方法返回具有给定键/值对的集合中的第一个元素。
1$collection = collect([ 2 ['name' => 'Regena', 'age' => null], 3 ['name' => 'Linda', 'age' => 14], 4 ['name' => 'Diego', 'age' => 23], 5 ['name' => 'Linda', 'age' => 84], 6]); 7 8$collection->firstWhere('name', 'Linda'); 9 10// ['name' => 'Linda', 'age' => 14]
你也可以调用带比较运算符的 firstWhere 方法。
1$collection->firstWhere('age', '>=', 18);2 3// ['name' => 'Diego', 'age' => 23]
像 where 方法一样,你可以向 firstWhere 方法传递一个参数。在这种情况下,firstWhere 方法将返回给定项目键的值为“真”的第一个项目。
1$collection->firstWhere('age');2 3// ['name' => 'Linda', 'age' => 14]
flatMap()
flatMap 方法遍历集合并将每个值传递给给定的闭包。闭包可以自由修改项目并返回它,从而形成一个新的修改后项目的集合。然后,数组将被展平一级。
1$collection = collect([ 2 ['name' => 'Sally'], 3 ['school' => 'Arkansas'], 4 ['age' => 28] 5]); 6 7$flattened = $collection->flatMap(function (array $values) { 8 return array_map('strtoupper', $values); 9});10 11$flattened->all();12 13// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];
flatten()
flatten 方法将多维集合展平为一维。
1$collection = collect([ 2 'name' => 'Taylor', 3 'languages' => [ 4 'PHP', 'JavaScript' 5 ] 6]); 7 8$flattened = $collection->flatten(); 9 10$flattened->all();11 12// ['Taylor', 'PHP', 'JavaScript'];
如有必要,你可以向 flatten 方法传递一个“深度”参数。
1$collection = collect([ 2 'Apple' => [ 3 [ 4 'name' => 'iPhone 6S', 5 'brand' => 'Apple' 6 ], 7 ], 8 'Samsung' => [ 9 [10 'name' => 'Galaxy S7',11 'brand' => 'Samsung'12 ],13 ],14]);15 16$products = $collection->flatten(1);17 18$products->values()->all();19 20/*21 [22 ['name' => 'iPhone 6S', 'brand' => 'Apple'],23 ['name' => 'Galaxy S7', 'brand' => 'Samsung'],24 ]25*/
在此示例中,如果不提供深度而调用 flatten,也会展平嵌套数组,结果为 ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']。提供深度允许你指定展平嵌套数组的层数。
flip()
flip 方法交换集合的键及其对应的值。
1$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);2 3$flipped = $collection->flip();4 5$flipped->all();6 7// ['Taylor' => 'name', 'Laravel' => 'framework']
forget()
forget 方法通过键从集合中删除一个项目。
1$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']); 2 3// Forget a single key... 4$collection->forget('name'); 5 6// ['framework' => 'Laravel'] 7 8// Forget multiple keys... 9$collection->forget(['name', 'framework']);10 11// []
与大多数其他集合方法不同,forget 不会返回新的修改后的集合;它会直接修改并返回调用它的集合。
forPage()
forPage 方法返回一个包含给定页码上可能存在的项目的新集合。该方法接受页码作为第一个参数,每页显示的项数作为第二个参数。
1$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);2 3$chunk = $collection->forPage(2, 3);4 5$chunk->all();6 7// [4, 5, 6]
fromJson()
静态 fromJson 方法通过使用 PHP 的 json_decode 函数解码给定 JSON 字符串来创建新的集合实例。
1use Illuminate\Support\Collection;2 3$json = json_encode([4 'name' => 'Taylor Otwell',5 'role' => 'Developer',6 'status' => 'Active',7]);8 9$collection = Collection::fromJson($json);
get()
get 方法返回给定键处的项目。如果键不存在,则返回 null。
1$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);2 3$value = $collection->get('name');4 5// Taylor
你可以选择传递默认值作为第二个参数。
1$collection = collect(['name' => 'Taylor', 'framework' => 'Laravel']);2 3$value = $collection->get('age', 34);4 5// 34
你甚至可以将回调作为方法的默认值传递。如果指定的键不存在,将返回回调的结果。
1$collection->get('email', function () {3});4
groupBy()
groupBy 方法根据给定键对集合的项目进行分组。
1$collection = collect([ 2 ['account_id' => 'account-x10', 'product' => 'Chair'], 3 ['account_id' => 'account-x10', 'product' => 'Bookcase'], 4 ['account_id' => 'account-x11', 'product' => 'Desk'], 5]); 6 7$grouped = $collection->groupBy('account_id'); 8 9$grouped->all();10 11/*12 [13 'account-x10' => [14 ['account_id' => 'account-x10', 'product' => 'Chair'],15 ['account_id' => 'account-x10', 'product' => 'Bookcase'],16 ],17 'account-x11' => [18 ['account_id' => 'account-x11', 'product' => 'Desk'],19 ],20 ]21*/
除了传递字符串 key 外,你还可以传递闭包。闭包应该返回你希望作为分组键的值。
1$grouped = $collection->groupBy(function (array $item, int $key) { 2 return substr($item['account_id'], -3); 3}); 4 5$grouped->all(); 6 7/* 8 [ 9 'x10' => [10 ['account_id' => 'account-x10', 'product' => 'Chair'],11 ['account_id' => 'account-x10', 'product' => 'Bookcase'],12 ],13 'x11' => [14 ['account_id' => 'account-x11', 'product' => 'Desk'],15 ],16 ]17*/
多个分组标准可以作为数组传递。每个数组元素将被应用到多维数组内的相应级别。
1$data = new Collection([ 2 10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']], 3 20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']], 4 30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']], 5 40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']], 6]); 7 8$result = $data->groupBy(['skill', function (array $item) { 9 return $item['roles'];10}], preserveKeys: true);11 12/*13[14 1 => [15 'Role_1' => [16 10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],17 20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],18 ],19 'Role_2' => [20 20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],21 ],22 'Role_3' => [23 10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],24 ],25 ],26 2 => [27 'Role_1' => [28 30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],29 ],30 'Role_2' => [31 40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],32 ],33 ],34];35*/
has()
has 方法确定给定键是否存在于集合中。
1$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]); 2 3$collection->has('product'); 4 5// true 6 7$collection->has(['product', 'amount']); 8 9// true10 11$collection->has(['amount', 'price']);12 13// false
hasAny()
hasAny 方法确定给定的键中是否有任何键存在于集合中。
1$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);2 3$collection->hasAny(['product', 'price']);4 5// true6 7$collection->hasAny(['name', 'price']);8 9// false
hasMany()
hasMany 方法确定集合是否包含多个项目。
1collect([])->hasMany(); 2 3// false 4 5collect(['1'])->hasMany(); 6 7// false 8 9collect([1, 2, 3])->hasMany();10 11// true12 13collect([14 ['age' => 2],15 ['age' => 3],16])->hasMany(fn ($item) => $item['age'] === 2)17 18// false
hasSole()
hasSole 方法确定集合是否包含单个项目(可选择匹配给定的条件)。
1collect([])->hasSole(); 2 3// false 4 5collect(['1'])->hasSole(); 6 7// true 8 9collect([1, 2, 3])->hasSole(fn (int $item) => $item === 2);10 11// true
implode()
implode 方法连接集合中的项目。其参数取决于集合中项目的类型。如果集合包含数组或对象,你应该传递你想要连接的属性键,以及你想要放在值之间的“胶水”字符串。
1$collection = collect([2 ['account_id' => 1, 'product' => 'Desk'],3 ['account_id' => 2, 'product' => 'Chair'],4]);5 6$collection->implode('product', ', ');7 8// 'Desk, Chair'
如果集合包含简单的字符串或数字值,你应该只将“胶水”作为方法的参数传递。
1collect([1, 2, 3, 4, 5])->implode('-');2 3// '1-2-3-4-5'
如果你想格式化正在连接的值,可以向 implode 方法传递闭包。
1$collection->implode(function (array $item, int $key) {2 return strtoupper($item['product']);3}, ', ');4 5// 'DESK, CHAIR'
intersect()
intersect 方法从原始集合中删除任何不存在于给定数组或集合中的值。结果集合将保留原始集合的键。
1$collection = collect(['Desk', 'Sofa', 'Chair']);2 3$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);4 5$intersect->all();6 7// [0 => 'Desk', 2 => 'Chair']
使用 Eloquent 集合 时,此方法的行为会发生改变。
intersectUsing()
intersectUsing 方法使用自定义回调来比较值,从原始集合中删除任何不存在于给定数组或集合中的值。结果集合将保留原始集合的键。
1$collection = collect(['Desk', 'Sofa', 'Chair']);2 3$intersect = $collection->intersectUsing(['desk', 'chair', 'bookcase'], function (string $a, string $b) {4 return strcasecmp($a, $b);5});6 7$intersect->all();8 9// [0 => 'Desk', 2 => 'Chair']
intersectAssoc()
intersectAssoc 方法将原始集合与另一个集合或数组进行比较,返回存在于所有给定集合中的键/值对。
1$collection = collect([ 2 'color' => 'red', 3 'size' => 'M', 4 'material' => 'cotton' 5]); 6 7$intersect = $collection->intersectAssoc([ 8 'color' => 'blue', 9 'size' => 'M',10 'material' => 'polyester'11]);12 13$intersect->all();14 15// ['size' => 'M']
intersectAssocUsing()
intersectAssocUsing 方法将原始集合与另一个集合或数组进行比较,使用自定义比较回调来确定键和值是否相等,返回两者中都存在的键/值对。
1$collection = collect([ 2 'color' => 'red', 3 'Size' => 'M', 4 'material' => 'cotton', 5]); 6 7$intersect = $collection->intersectAssocUsing([ 8 'color' => 'blue', 9 'size' => 'M',10 'material' => 'polyester',11], function (string $a, string $b) {12 return strcasecmp($a, $b);13});14 15$intersect->all();16 17// ['Size' => 'M']
intersectByKeys()
intersectByKeys 方法从原始集合中删除任何键及其对应值,这些键不存在于给定数组或集合中。
1$collection = collect([ 2 'serial' => 'UX301', 'type' => 'screen', 'year' => 2009, 3]); 4 5$intersect = $collection->intersectByKeys([ 6 'reference' => 'UX404', 'type' => 'tab', 'year' => 2011, 7]); 8 9$intersect->all();10 11// ['type' => 'screen', 'year' => 2009]
isEmpty()
如果集合为空,isEmpty 方法返回 true;否则返回 false。
1collect([])->isEmpty();2 3// true
isNotEmpty()
如果集合不为空,isNotEmpty 方法返回 true;否则返回 false。
1collect([])->isNotEmpty();2 3// false
join()
join 方法使用字符串连接集合的值。使用此方法的第二个参数,你还可以指定最后一个元素应该如何追加到字符串中。
1collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'2collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'3collect(['a', 'b'])->join(', ', ' and '); // 'a and b'4collect(['a'])->join(', ', ' and '); // 'a'5collect([])->join(', ', ' and '); // ''
keyBy()
keyBy 方法通过给定键对集合进行索引。如果多个项目具有相同的键,则只有最后一个会出现在新集合中。
1$collection = collect([ 2 ['product_id' => 'prod-100', 'name' => 'Desk'], 3 ['product_id' => 'prod-200', 'name' => 'Chair'], 4]); 5 6$keyed = $collection->keyBy('product_id'); 7 8$keyed->all(); 9 10/*11 [12 'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],13 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],14 ]15*/
你也可以向该方法传递回调。回调应该返回用于索引集合的值。
1$keyed = $collection->keyBy(function (array $item, int $key) { 2 return strtoupper($item['product_id']); 3}); 4 5$keyed->all(); 6 7/* 8 [ 9 'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],10 'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],11 ]12*/
keys()
keys 方法返回集合的所有键。
1$collection = collect([ 2 'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'], 3 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'], 4]); 5 6$keys = $collection->keys(); 7 8$keys->all(); 9 10// ['prod-100', 'prod-200']
last()
last 方法返回集合中通过给定真值测试的最后一个元素。
1collect([1, 2, 3, 4])->last(function (int $value, int $key) {2 return $value < 3;3});4 5// 2
你也可以在不带参数的情况下调用 last 方法来获取集合中的最后一个元素。如果集合为空,则返回 null。
1collect([1, 2, 3, 4])->last();2 3// 4
lazy()
lazy 方法从底层项目数组返回一个新的 LazyCollection 实例。
1$lazyCollection = collect([1, 2, 3, 4])->lazy();2 3$lazyCollection::class;4 5// Illuminate\Support\LazyCollection6 7$lazyCollection->all();8 9// [1, 2, 3, 4]
当你需要对包含大量项目的巨大 Collection 执行转换时,这特别有用。
1$count = $hugeCollection2 ->lazy()3 ->where('country', 'FR')4 ->where('balance', '>', '100')5 ->count();
通过将集合转换为 LazyCollection,我们避免了分配大量额外内存。虽然原始集合仍将其值保存在内存中,但后续的过滤器不会。因此,在过滤集合结果时,几乎不会分配额外的内存。
macro()
静态 macro 方法允许你在运行时向 Collection 类添加方法。有关更多信息,请参阅关于 扩展集合 的文档。
make()
静态 make 方法创建一个新的集合实例。请参阅 创建集合 一节。
1use Illuminate\Support\Collection;2 3$collection = Collection::make([1, 2, 3]);
map()
map 方法遍历集合并将每个值传递给给定的回调。回调可以自由修改项目并返回它,从而形成一个新的修改后项目的集合。
1$collection = collect([1, 2, 3, 4, 5]);2 3$multiplied = $collection->map(function (int $item, int $key) {4 return $item * 2;5});6 7$multiplied->all();8 9// [2, 4, 6, 8, 10]
与大多数其他集合方法一样,map 返回一个新的集合实例;它不会修改调用它的集合。如果你想转换原始集合,请使用 transform 方法。
mapInto()
mapInto() 方法迭代集合,通过将值传入构造函数来创建给定类的新实例。
1class Currency 2{ 3 /** 4 * Create a new currency instance. 5 */ 6 function __construct( 7 public string $code, 8 ) {} 9}10 11$collection = collect(['USD', 'EUR', 'GBP']);12 13$currencies = $collection->mapInto(Currency::class);14 15$currencies->all();16 17// [Currency('USD'), Currency('EUR'), Currency('GBP')]
mapSpread()
mapSpread 方法迭代集合中的项目,并将每个嵌套项目的值传递给给定的闭包。闭包可以自由修改项目并返回它,从而形成一个新的修改后项目的集合。
1$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); 2 3$chunks = $collection->chunk(2); 4 5$sequence = $chunks->mapSpread(function (int $even, int $odd) { 6 return $even + $odd; 7}); 8 9$sequence->all();10 11// [1, 5, 9, 13, 17]
mapToGroups()
mapToGroups 方法根据给定的闭包对集合中的项目进行分组。闭包应该返回一个包含单个键/值对的关联数组,从而形成一个新的分组值集合。
1$collection = collect([ 2 [ 3 'name' => 'John Doe', 4 'department' => 'Sales', 5 ], 6 [ 7 'name' => 'Jane Doe', 8 'department' => 'Sales', 9 ],10 [11 'name' => 'Johnny Doe',12 'department' => 'Marketing',13 ]14]);15 16$grouped = $collection->mapToGroups(function (array $item, int $key) {17 return [$item['department'] => $item['name']];18});19 20$grouped->all();21 22/*23 [24 'Sales' => ['John Doe', 'Jane Doe'],25 'Marketing' => ['Johnny Doe'],26 ]27*/28 29$grouped->get('Sales')->all();30 31// ['John Doe', 'Jane Doe']
mapWithKeys()
mapWithKeys 方法遍历集合并将每个值传递给给定的回调。回调应该返回一个包含单个键/值对的关联数组。
1$collection = collect([ 2 [ 3 'name' => 'John', 4 'department' => 'Sales', 6 ], 7 [ 8 'name' => 'Jane', 9 'department' => 'Marketing',11 ]12]);13 14$keyed = $collection->mapWithKeys(function (array $item, int $key) {15 return [$item['email'] => $item['name']];16});17 18$keyed->all();19 20/*21 [22 '[email protected]' => 'John',23 '[email protected]' => 'Jane',24 ]25*/
max()
max 方法返回给定键的最大值。
1$max = collect([ 2 ['foo' => 10], 3 ['foo' => 20] 4])->max('foo'); 5 6// 20 7 8$max = collect([1, 2, 3, 4, 5])->max(); 9 10// 5
median()
median 方法返回给定键的 中位数。
1$median = collect([ 2 ['foo' => 10], 3 ['foo' => 10], 4 ['foo' => 20], 5 ['foo' => 40] 6])->median('foo'); 7 8// 15 9 10$median = collect([1, 1, 2, 4])->median();11 12// 1.5
merge()
merge 方法将给定数组或集合与原始集合合并。如果给定项目中的字符串键与原始集合中的字符串键匹配,则给定项目的值将覆盖原始集合中的值。
1$collection = collect(['product_id' => 1, 'price' => 100]);2 3$merged = $collection->merge(['price' => 200, 'discount' => false]);4 5$merged->all();6 7// ['product_id' => 1, 'price' => 200, 'discount' => false]
如果给定项目的键是数字,这些值将被追加到集合的末尾。
1$collection = collect(['Desk', 'Chair']);2 3$merged = $collection->merge(['Bookcase', 'Door']);4 5$merged->all();6 7// ['Desk', 'Chair', 'Bookcase', 'Door']
mergeRecursive()
mergeRecursive 方法递归地将给定数组或集合与原始集合合并。如果给定项目中的字符串键与原始集合中的字符串键匹配,则这些键的值将被合并为一个数组,并且此操作是递归进行的。
1$collection = collect(['product_id' => 1, 'price' => 100]); 2 3$merged = $collection->mergeRecursive([ 4 'product_id' => 2, 5 'price' => 200, 6 'discount' => false 7]); 8 9$merged->all();10 11// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
min()
min 方法返回给定键的最小值。
1$min = collect([ 2 ['foo' => 10], 3 ['foo' => 20] 4])->min('foo'); 5 6// 10 7 8$min = collect([1, 2, 3, 4, 5])->min(); 9 10// 1
mode()
mode 方法返回给定键的 众数。
1$mode = collect([ 2 ['foo' => 10], 3 ['foo' => 10], 4 ['foo' => 20], 5 ['foo' => 40] 6])->mode('foo'); 7 8// [10] 9 10$mode = collect([1, 1, 2, 4])->mode();11 12// [1]13 14$mode = collect([1, 1, 2, 2])->mode();15 16// [1, 2]
multiply()
multiply 方法创建集合中所有项目的指定副本数量。
1$users = collect([ 4])->multiply(3); 5 6/* 7 [ 8 ['name' => 'User #1', 'email' => '[email protected]'], 9 ['name' => 'User #2', 'email' => '[email protected]'],10 ['name' => 'User #1', 'email' => '[email protected]'],11 ['name' => 'User #2', 'email' => '[email protected]'],12 ['name' => 'User #1', 'email' => '[email protected]'],13 ['name' => 'User #2', 'email' => '[email protected]'],14 ]15*/
nth()
nth 方法创建一个由每 n 个元素组成的新集合。
1$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);2 3$collection->nth(4);4 5// ['a', 'e']
你可以选择传递一个起始偏移量作为第二个参数。
1$collection->nth(4, 1);2 3// ['b', 'f']
only()
only 方法返回集合中具有指定键的项目。
1$collection = collect([ 2 'product_id' => 1, 3 'name' => 'Desk', 4 'price' => 100, 5 'discount' => false 6]); 7 8$filtered = $collection->only(['product_id', 'name']); 9 10$filtered->all();11 12// ['product_id' => 1, 'name' => 'Desk']
关于 only 的反向操作,请参阅 except 方法。
使用 Eloquent 集合 时,此方法的行为会发生改变。
pad()
pad 方法将数组填充为给定值,直到达到指定大小。此方法的行为类似于 PHP 的 array_pad 函数。
要向左填充,你应该指定一个负数大小。如果给定大小的绝对值小于或等于数组长度,则不会进行任何填充。
1$collection = collect(['A', 'B', 'C']); 2 3$filtered = $collection->pad(5, 0); 4 5$filtered->all(); 6 7// ['A', 'B', 'C', 0, 0] 8 9$filtered = $collection->pad(-5, 0);10 11$filtered->all();12 13// [0, 0, 'A', 'B', 'C']
partition()
partition 方法可以与 PHP 数组解构相结合,将通过给定真值测试的元素与未通过的元素分开。
1$collection = collect([1, 2, 3, 4, 5, 6]); 2 3[$underThree, $equalOrAboveThree] = $collection->partition(function (int $i) { 4 return $i < 3; 5}); 6 7$underThree->all(); 8 9// [1, 2]10 11$equalOrAboveThree->all();12 13// [3, 4, 5, 6]
与 Eloquent 集合 交互时,此方法的行为会发生改变。
percentage()
percentage 方法可用于快速确定集合中通过给定真值测试的项目的百分比。
1$collection = collect([1, 1, 2, 2, 2, 3]);2 3$percentage = $collection->percentage(fn (int $value) => $value === 1);4 5// 33.33
默认情况下,百分比将四舍五入到小数点后两位。但是,你可以通过向方法提供第二个参数来自定义此行为。
1$percentage = $collection->percentage(fn (int $value) => $value === 1, precision: 3);2 3// 33.333
pipe()
pipe 方法将集合传递给给定的闭包并返回执行闭包的结果。
1$collection = collect([1, 2, 3]);2 3$piped = $collection->pipe(function (Collection $collection) {4 return $collection->sum();5});6 7// 6
pipeInto()
pipeInto 方法创建给定类的新实例并将集合传入构造函数。
1class ResourceCollection 2{ 3 /** 4 * Create a new ResourceCollection instance. 5 */ 6 public function __construct( 7 public Collection $collection, 8 ) {} 9}10 11$collection = collect([1, 2, 3]);12 13$resource = $collection->pipeInto(ResourceCollection::class);14 15$resource->collection->all();16 17// [1, 2, 3]
pipeThrough()
pipeThrough 方法将集合传递给给定的闭包数组并返回执行闭包的结果。
1use Illuminate\Support\Collection; 2 3$collection = collect([1, 2, 3]); 4 5$result = $collection->pipeThrough([ 6 function (Collection $collection) { 7 return $collection->merge([4, 5]); 8 }, 9 function (Collection $collection) {10 return $collection->sum();11 },12]);13 14// 15
pluck()
pluck 方法检索给定键的所有值。
1$collection = collect([ 2 ['product_id' => 'prod-100', 'name' => 'Desk'], 3 ['product_id' => 'prod-200', 'name' => 'Chair'], 4]); 5 6$plucked = $collection->pluck('name'); 7 8$plucked->all(); 9 10// ['Desk', 'Chair']
你还可以指定希望如何对结果集合进行索引。
1$plucked = $collection->pluck('name', 'product_id');2 3$plucked->all();4 5// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
pluck 方法还支持使用“点”符号检索嵌套值。
1$collection = collect([ 2 [ 3 'name' => 'Laracon', 4 'speakers' => [ 5 'first_day' => ['Rosa', 'Judith'], 6 ], 7 ], 8 [ 9 'name' => 'VueConf',10 'speakers' => [11 'first_day' => ['Abigail', 'Joey'],12 ],13 ],14]);15 16$plucked = $collection->pluck('speakers.first_day');17 18$plucked->all();19 20// [['Rosa', 'Judith'], ['Abigail', 'Joey']]
如果存在重复键,最后一个匹配的元素将被插入到被抽取的集合中。
1$collection = collect([ 2 ['brand' => 'Tesla', 'color' => 'red'], 3 ['brand' => 'Pagani', 'color' => 'white'], 4 ['brand' => 'Tesla', 'color' => 'black'], 5 ['brand' => 'Pagani', 'color' => 'orange'], 6]); 7 8$plucked = $collection->pluck('color', 'brand'); 9 10$plucked->all();11 12// ['Tesla' => 'black', 'Pagani' => 'orange']
pop()
pop 方法删除并返回集合中的最后一个项目。如果集合为空,则返回 null。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->pop();4 5// 56 7$collection->all();8 9// [1, 2, 3, 4]
你可以向 pop 方法传递一个整数,以从集合末尾删除并返回多个项目。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->pop(3);4 5// collect([5, 4, 3])6 7$collection->all();8 9// [1, 2]
prepend()
prepend 方法将一个项目添加到集合的开头。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->prepend(0);4 5$collection->all();6 7// [0, 1, 2, 3, 4, 5]
你也可以传递第二个参数来指定被预置项目的键。
1$collection = collect(['one' => 1, 'two' => 2]);2 3$collection->prepend(0, 'zero');4 5$collection->all();6 7// ['zero' => 0, 'one' => 1, 'two' => 2]
pull()
pull 方法通过键从集合中删除并返回一个项目。
1$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);2 3$collection->pull('name');4 5// 'Desk'6 7$collection->all();8 9// ['product_id' => 'prod-100']
push()
push 方法将一个项目追加到集合的末尾。
1$collection = collect([1, 2, 3, 4]);2 3$collection->push(5);4 5$collection->all();6 7// [1, 2, 3, 4, 5]
你也可以提供多个项目以追加到集合的末尾。
1$collection = collect([1, 2, 3, 4]);2 3$collection->push(5, 6, 7);4 5$collection->all();6 7// [1, 2, 3, 4, 5, 6, 7]
put()
put 方法在集合中设置给定的键和值。
1$collection = collect(['product_id' => 1, 'name' => 'Desk']);2 3$collection->put('price', 100);4 5$collection->all();6 7// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
random()
random 方法从集合中返回一个随机项目。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->random();4 5// 4 - (retrieved randomly)
你可以向 random 传递一个整数来指定要随机检索多少个项目。显式传递要接收的项目数时,总是会返回一个项目集合。
1$random = $collection->random(3);2 3$random->all();4 5// [2, 4, 5] - (retrieved randomly)
如果集合实例中的项目数少于请求数,random 方法将抛出 InvalidArgumentException。
random 方法还接受一个闭包,该闭包将接收当前的集合实例。
1use Illuminate\Support\Collection;2 3$random = $collection->random(fn (Collection $items) => min(10, count($items)));4 5$random->all();6 7// [1, 2, 3, 4, 5] - (retrieved randomly)
range()
range 方法返回一个包含指定范围内整数的集合。
1$collection = collect()->range(3, 6);2 3$collection->all();4 5// [3, 4, 5, 6]
reduce()
reduce 方法将集合归约为单个值,将每次迭代的结果传入下一次迭代。
1$collection = collect([1, 2, 3]);2 3$total = $collection->reduce(function (?int $carry, int $item) {4 return $carry + $item;5});6 7// 6
第一次迭代时 $carry 的值为 null;但是,你可以通过向 reduce 传递第二个参数来指定其初始值。
1$collection->reduce(function (int $carry, int $item) {2 return $carry + $item;3}, 4);4 5// 10
reduce 方法还会将数组键传递给给定的回调。
1$collection = collect([ 2 'usd' => 1400, 3 'gbp' => 1200, 4 'eur' => 1000, 5]); 6 7$ratio = [ 8 'usd' => 1, 9 'gbp' => 1.37,10 'eur' => 1.22,11];12 13$collection->reduce(function (int $carry, int $value, string $key) use ($ratio) {14 return $carry + ($value * $ratio[$key]);15}, 0);16 17// 4264
reduceSpread()
reduceSpread 方法将集合归约为一个值数组,并将每次迭代的结果传入下一次迭代。此方法类似于 reduce 方法;但是,它可以接受多个初始值。
1[$creditsRemaining, $batch] = Image::where('status', 'unprocessed') 2 ->get() 3 ->reduceSpread(function (int $creditsRemaining, Collection $batch, Image $image) { 4 if ($creditsRemaining >= $image->creditsRequired()) { 5 $batch->push($image); 6 7 $creditsRemaining -= $image->creditsRequired(); 8 } 9 10 return [$creditsRemaining, $batch];11 }, $creditsAvailable, collect());
reject()
reject 方法使用给定的闭包过滤集合。如果项目应该从结果集合中删除,闭包应该返回 true。
1$collection = collect([1, 2, 3, 4]);2 3$filtered = $collection->reject(function (int $value, int $key) {4 return $value > 2;5});6 7$filtered->all();8 9// [1, 2]
关于 reject 方法的反向操作,请参阅 filter 方法。
replace()
replace 方法的行为类似于 merge;但是,除了覆盖具有字符串键的匹配项目外,replace 方法还将覆盖集合中具有匹配数字键的项目。
1$collection = collect(['Taylor', 'Abigail', 'James']);2 3$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);4 5$replaced->all();6 7// ['Taylor', 'Victoria', 'James', 'Finn']
replaceRecursive()
replaceRecursive 方法的行为类似于 replace,但它会递归到数组中,并将相同的替换过程应用于内部值。
1$collection = collect([ 2 'Taylor', 3 'Abigail', 4 [ 5 'James', 6 'Victoria', 7 'Finn' 8 ] 9]);10 11$replaced = $collection->replaceRecursive([12 'Charlie',13 2 => [1 => 'King']14]);15 16$replaced->all();17 18// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]
reverse()
reverse 方法反转集合项目的顺序,保留原始键。
1$collection = collect(['a', 'b', 'c', 'd', 'e']); 2 3$reversed = $collection->reverse(); 4 5$reversed->all(); 6 7/* 8 [ 9 4 => 'e',10 3 => 'd',11 2 => 'c',12 1 => 'b',13 0 => 'a',14 ]15*/
search()
search 方法在集合中搜索给定值,如果找到则返回其键。如果未找到项目,则返回 false。
1$collection = collect([2, 4, 6, 8]);2 3$collection->search(4);4 5// 1
搜索使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。要使用“严格”比较,请将 true 作为第二个参数传递给该方法。
1collect([2, 4, 6, 8])->search('4', strict: true);2 3// false
或者,你可以提供自己的闭包来搜索通过给定真值测试的第一个项目。
1collect([2, 4, 6, 8])->search(function (int $item, int $key) {2 return $item > 5;3});4 5// 2
select()
select 方法从集合中选择给定的键,类似于 SQL 的 SELECT 语句。
1$users = collect([ 2 ['name' => 'Taylor Otwell', 'role' => 'Developer', 'status' => 'active'], 3 ['name' => 'Victoria Faith', 'role' => 'Researcher', 'status' => 'active'], 4]); 5 6$users->select(['name', 'role']); 7 8/* 9 [10 ['name' => 'Taylor Otwell', 'role' => 'Developer'],11 ['name' => 'Victoria Faith', 'role' => 'Researcher'],12 ],13*/
shift()
shift 方法删除并返回集合中的第一个项目。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->shift();4 5// 16 7$collection->all();8 9// [2, 3, 4, 5]
你可以向 shift 方法传递一个整数,以从集合开头删除并返回多个项目。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->shift(3);4 5// collect([1, 2, 3])6 7$collection->all();8 9// [4, 5]
shuffle()
shuffle 方法随机打乱集合中的项目。
1$collection = collect([1, 2, 3, 4, 5]);2 3$shuffled = $collection->shuffle();4 5$shuffled->all();6 7// [3, 2, 5, 1, 4] - (generated randomly)
skip()
skip 方法返回一个新的集合,其中包含从集合开头删除的给定数量的元素。
1$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);2 3$collection = $collection->skip(4);4 5$collection->all();6 7// [5, 6, 7, 8, 9, 10]
skipUntil()
skipUntil 方法在给定回调返回 false 时跳过集合中的项目。一旦回调返回 true,所有剩余的项目将作为新集合返回。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->skipUntil(function (int $item) {4 return $item >= 3;5});6 7$subset->all();8 9// [3, 4]
你也可以向 skipUntil 方法传递一个简单值,以跳过所有项目直到找到给定值。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->skipUntil(3);4 5$subset->all();6 7// [3, 4]
如果未找到给定值,或者回调从未返回 true,则 skipUntil 方法将返回一个空集合。
skipWhile()
skipWhile 方法在给定回调返回 true 时跳过集合中的项目。一旦回调返回 false,所有剩余的项目将作为新集合返回。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->skipWhile(function (int $item) {4 return $item <= 3;5});6 7$subset->all();8 9// [4]
如果回调从未返回 false,则 skipWhile 方法将返回一个空集合。
slice()
slice 方法返回从给定索引开始的集合切片。
1$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);2 3$slice = $collection->slice(4);4 5$slice->all();6 7// [5, 6, 7, 8, 9, 10]
如果你想限制返回切片的大小,将所需大小作为第二个参数传递给该方法。
1$slice = $collection->slice(4, 2);2 3$slice->all();4 5// [5, 6]
返回的切片默认保留键。如果你不想保留原始键,可以使用 values 方法重新索引它们。
sliding()
sliding 方法返回一个新的块集合,代表集合中项目的“滑动窗口”视图。
1$collection = collect([1, 2, 3, 4, 5]);2 3$chunks = $collection->sliding(2);4 5$chunks->toArray();6 7// [[1, 2], [2, 3], [3, 4], [4, 5]]
这与 eachSpread 方法结合使用特别有用。
1$transactions->sliding(2)->eachSpread(function (Collection $previous, Collection $current) {2 $current->total = $previous->total + $current->amount;3});
你可以选择传递第二个“步长”值,它决定了每个块的第一个项目之间的距离。
1$collection = collect([1, 2, 3, 4, 5]);2 3$chunks = $collection->sliding(3, step: 2);4 5$chunks->toArray();6 7// [[1, 2, 3], [3, 4, 5]]
sole()
sole 方法返回集合中通过给定真值测试的第一个元素,但前提是真值测试仅匹配一个元素。
1collect([1, 2, 3, 4])->sole(function (int $value, int $key) {2 return $value === 2;3});4 5// 2
你也可以向 sole 方法传递键/值对,它将返回集合中匹配给定对的第一个元素,但前提是完全匹配一个元素。
1$collection = collect([2 ['product' => 'Desk', 'price' => 200],3 ['product' => 'Chair', 'price' => 100],4]);5 6$collection->sole('product', 'Chair');7 8// ['product' => 'Chair', 'price' => 100]
或者,如果没有元素,你也可以在不带参数的情况下调用 sole 方法,以获取集合中仅有的一个元素。
1$collection = collect([2 ['product' => 'Desk', 'price' => 200],3]);4 5$collection->sole();6 7// ['product' => 'Desk', 'price' => 200]
如果集合中没有应由 sole 方法返回的元素,将抛出 \Illuminate\Collections\ItemNotFoundException 异常。如果有多个元素应被返回,将抛出 \Illuminate\Collections\MultipleItemsFoundException。
some()
contains 方法的别名。
sort()
sort 方法对集合进行排序。排序后的集合保留原始数组键,因此在以下示例中,我们将使用 values 方法将键重置为连续编号的索引。
1$collection = collect([5, 3, 1, 2, 4]);2 3$sorted = $collection->sort();4 5$sorted->values()->all();6 7// [1, 2, 3, 4, 5]
如果你的排序需求更高级,你可以将带有你自己的算法的闭包传递给 sort。请参阅 PHP 关于 uasort 的文档,这是集合的 sort 方法内部调用的函数。
如果你需要对嵌套数组或对象的集合进行排序,请参阅 sortBy 和 sortByDesc 方法。
sortBy()
sortBy 方法按给定键对集合进行排序。排序后的集合保留原始数组键,因此在以下示例中,我们将使用 values 方法将键重置为连续编号的索引。
1$collection = collect([ 2 ['name' => 'Desk', 'price' => 200], 3 ['name' => 'Chair', 'price' => 100], 4 ['name' => 'Bookcase', 'price' => 150], 5]); 6 7$sorted = $collection->sortBy('price'); 8 9$sorted->values()->all();10 11/*12 [13 ['name' => 'Chair', 'price' => 100],14 ['name' => 'Bookcase', 'price' => 150],15 ['name' => 'Desk', 'price' => 200],16 ]17*/
sortBy 方法接受 排序标志 作为其第二个参数。
1$collection = collect([ 2 ['title' => 'Item 1'], 3 ['title' => 'Item 12'], 4 ['title' => 'Item 3'], 5]); 6 7$sorted = $collection->sortBy('title', SORT_NATURAL); 8 9$sorted->values()->all();10 11/*12 [13 ['title' => 'Item 1'],14 ['title' => 'Item 3'],15 ['title' => 'Item 12'],16 ]17*/
或者,你可以传递自己的闭包来确定如何对集合的值进行排序。
1$collection = collect([ 2 ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']], 3 ['name' => 'Chair', 'colors' => ['Black']], 4 ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']], 5]); 6 7$sorted = $collection->sortBy(function (array $product, int $key) { 8 return count($product['colors']); 9});10 11$sorted->values()->all();12 13/*14 [15 ['name' => 'Chair', 'colors' => ['Black']],16 ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],17 ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],18 ]19*/
如果你想按多个属性对集合进行排序,可以向 sortBy 方法传递一系列排序操作。每个排序操作应该是一个由你想要排序的属性和所需排序方向组成的数组。
1$collection = collect([ 2 ['name' => 'Taylor Otwell', 'age' => 34], 3 ['name' => 'Abigail Otwell', 'age' => 30], 4 ['name' => 'Taylor Otwell', 'age' => 36], 5 ['name' => 'Abigail Otwell', 'age' => 32], 6]); 7 8$sorted = $collection->sortBy([ 9 ['name', 'asc'],10 ['age', 'desc'],11]);12 13$sorted->values()->all();14 15/*16 [17 ['name' => 'Abigail Otwell', 'age' => 32],18 ['name' => 'Abigail Otwell', 'age' => 30],19 ['name' => 'Taylor Otwell', 'age' => 36],20 ['name' => 'Taylor Otwell', 'age' => 34],21 ]22*/
按多个属性对集合进行排序时,你还可以提供定义每个排序操作的闭包。
1$collection = collect([ 2 ['name' => 'Taylor Otwell', 'age' => 34], 3 ['name' => 'Abigail Otwell', 'age' => 30], 4 ['name' => 'Taylor Otwell', 'age' => 36], 5 ['name' => 'Abigail Otwell', 'age' => 32], 6]); 7 8$sorted = $collection->sortBy([ 9 fn (array $a, array $b) => $a['name'] <=> $b['name'],10 fn (array $a, array $b) => $b['age'] <=> $a['age'],11]);12 13$sorted->values()->all();14 15/*16 [17 ['name' => 'Abigail Otwell', 'age' => 32],18 ['name' => 'Abigail Otwell', 'age' => 30],19 ['name' => 'Taylor Otwell', 'age' => 36],20 ['name' => 'Taylor Otwell', 'age' => 34],21 ]22*/
sortByDesc()
此方法具有与 sortBy 方法相同的签名,但将按相反顺序对集合进行排序。
sortDesc()
此方法将按与 sort 方法相反的顺序对集合进行排序。
1$collection = collect([5, 3, 1, 2, 4]);2 3$sorted = $collection->sortDesc();4 5$sorted->values()->all();6 7// [5, 4, 3, 2, 1]
与 sort 不同,你不能向 sortDesc 传递闭包。相反,你应该使用 sort 方法并反转你的比较。
sortKeys()
sortKeys 方法根据底层关联数组的键对集合进行排序。
1$collection = collect([ 2 'id' => 22345, 3 'first' => 'John', 4 'last' => 'Doe', 5]); 6 7$sorted = $collection->sortKeys(); 8 9$sorted->all();10 11/*12 [13 'first' => 'John',14 'id' => 22345,15 'last' => 'Doe',16 ]17*/
sortKeysDesc()
此方法具有与 sortKeys 方法相同的签名,但将按相反顺序对集合进行排序。
sortKeysUsing()
sortKeysUsing 方法使用回调根据底层关联数组的键对集合进行排序。
1$collection = collect([ 2 'ID' => 22345, 3 'first' => 'John', 4 'last' => 'Doe', 5]); 6 7$sorted = $collection->sortKeysUsing('strnatcasecmp'); 8 9$sorted->all();10 11/*12 [13 'first' => 'John',14 'ID' => 22345,15 'last' => 'Doe',16 ]17*/
回调必须是一个比较函数,返回小于、等于或大于零的整数。有关更多信息,请参阅 PHP 关于 uksort 的文档,这是 sortKeysUsing 方法内部调用的 PHP 函数。
splice()
splice 方法从指定索引处删除并返回项目切片。
1$collection = collect([1, 2, 3, 4, 5]); 2 3$chunk = $collection->splice(2); 4 5$chunk->all(); 6 7// [3, 4, 5] 8 9$collection->all();10 11// [1, 2]
你可以传递第二个参数来限制结果集合的大小。
1$collection = collect([1, 2, 3, 4, 5]); 2 3$chunk = $collection->splice(2, 1); 4 5$chunk->all(); 6 7// [3] 8 9$collection->all();10 11// [1, 2, 4, 5]
此外,你可以传递包含新项目的第三个参数,以替换从集合中删除的项目。
1$collection = collect([1, 2, 3, 4, 5]); 2 3$chunk = $collection->splice(2, 1, [10, 11]); 4 5$chunk->all(); 6 7// [3] 8 9$collection->all();10 11// [1, 2, 10, 11, 4, 5]
split()
split 方法将集合拆分为给定的组数。
1$collection = collect([1, 2, 3, 4, 5]);2 3$groups = $collection->split(3);4 5$groups->all();6 7// [[1, 2], [3, 4], [5]]
splitIn()
splitIn 方法将集合拆分为给定的组数,在将剩余部分分配给最终组之前,完全填充非终端组。
1$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);2 3$groups = $collection->splitIn(3);4 5$groups->all();6 7// [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
sum()
sum 方法返回集合中所有项目的总和。
1collect([1, 2, 3, 4, 5])->sum();2 3// 15
如果集合包含嵌套数组或对象,你应该传递一个键,该键将用于确定要对哪些值求和。
1$collection = collect([2 ['name' => 'JavaScript: The Good Parts', 'pages' => 176],3 ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],4]);5 6$collection->sum('pages');7 8// 1272
此外,你还可以传递自己的闭包来确定集合的哪些值要求和。
1$collection = collect([ 2 ['name' => 'Chair', 'colors' => ['Black']], 3 ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']], 4 ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']], 5]); 6 7$collection->sum(function (array $product) { 8 return count($product['colors']); 9});10 11// 6
take()
take 方法返回带有指定项目数的新集合。
1$collection = collect([0, 1, 2, 3, 4, 5]);2 3$chunk = $collection->take(3);4 5$chunk->all();6 7// [0, 1, 2]
你也可以传递一个负整数,从集合末尾获取指定数量的项目。
1$collection = collect([0, 1, 2, 3, 4, 5]);2 3$chunk = $collection->take(-2);4 5$chunk->all();6 7// [4, 5]
takeUntil()
takeUntil 方法在给定回调返回 true 之前返回集合中的项目。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->takeUntil(function (int $item) {4 return $item >= 3;5});6 7$subset->all();8 9// [1, 2]
你也可以向 takeUntil 方法传递一个简单值,以获取直到找到给定值之前的项目。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->takeUntil(3);4 5$subset->all();6 7// [1, 2]
如果未找到给定值,或者回调从未返回 true,则 takeUntil 方法将返回集合中的所有项目。
takeWhile()
takeWhile 方法在给定回调返回 false 之前返回集合中的项目。
1$collection = collect([1, 2, 3, 4]);2 3$subset = $collection->takeWhile(function (int $item) {4 return $item < 3;5});6 7$subset->all();8 9// [1, 2]
如果回调从未返回 false,则 takeWhile 方法将返回集合中的所有项目。
tap()
tap 方法将集合传递给给定的回调,允许你在特定点“点击”进入集合,并在不影响集合本身的情况下对项目执行某些操作。然后 tap 方法返回集合。
1collect([2, 4, 3, 1, 5])2 ->sort()3 ->tap(function (Collection $collection) {4 Log::debug('Values after sorting', $collection->values()->all());5 })6 ->shift();7 8// 1
times()
静态 times 方法通过指定次数调用给定的闭包来创建新的集合。
1$collection = Collection::times(10, function (int $number) {2 return $number * 9;3});4 5$collection->all();6 7// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
toArray()
toArray 方法将集合转换为普通的 PHP array。如果集合的值是 Eloquent 模型,模型也将被转换为数组。
1$collection = collect(['name' => 'Desk', 'price' => 200]);2 3$collection->toArray();4 5/*6 [7 ['name' => 'Desk', 'price' => 200],8 ]9*/
toArray 还会将所有属于 Arrayable 实例的嵌套对象转换为数组。如果你想获取集合底层的原始数组,请改用 all 方法。
toJson()
toJson 方法将集合转换为 JSON 序列化的字符串。
1$collection = collect(['name' => 'Desk', 'price' => 200]);2 3$collection->toJson();4 5// '{"name":"Desk", "price":200}'
toPrettyJson()
toPrettyJson 方法使用 JSON_PRETTY_PRINT 选项将集合转换为格式化的 JSON 字符串。
1$collection = collect(['name' => 'Desk', 'price' => 200]);2 3$collection->toPrettyJson();
transform()
transform 方法迭代集合并使用集合中的每个项目调用给定的回调。集合中的项目将被回调返回的值所替换。
1$collection = collect([1, 2, 3, 4, 5]);2 3$collection->transform(function (int $item, int $key) {4 return $item * 2;5});6 7$collection->all();8 9// [2, 4, 6, 8, 10]
与大多数其他集合方法不同,transform 会修改集合本身。如果你希望创建一个新的集合,请使用 map 方法。
undot()
undot 方法将使用“点”符号的单维集合展开为多维集合。
1$person = collect([ 2 'name.first_name' => 'Marie', 3 'name.last_name' => 'Valentine', 4 'address.line_1' => '2992 Eagle Drive', 5 'address.line_2' => '', 6 'address.suburb' => 'Detroit', 7 'address.state' => 'MI', 8 'address.postcode' => '48219' 9]);10 11$person = $person->undot();12 13$person->toArray();14 15/*16 [17 "name" => [18 "first_name" => "Marie",19 "last_name" => "Valentine",20 ],21 "address" => [22 "line_1" => "2992 Eagle Drive",23 "line_2" => "",24 "suburb" => "Detroit",25 "state" => "MI",26 "postcode" => "48219",27 ],28 ]29*/
union()
union 方法将给定数组添加到集合中。如果给定数组包含原始集合中已有的键,则原始集合的值将被优先保留。
1$collection = collect([1 => ['a'], 2 => ['b']]);2 3$union = $collection->union([3 => ['c'], 1 => ['d']]);4 5$union->all();6 7// [1 => ['a'], 2 => ['b'], 3 => ['c']]
unique()
unique 方法返回集合中所有唯一项目。返回的集合保留原始数组键,因此在以下示例中,我们将使用 values 方法将键重置为连续编号的索引。
1$collection = collect([1, 1, 2, 2, 3, 4, 2]);2 3$unique = $collection->unique();4 5$unique->values()->all();6 7// [1, 2, 3, 4]
处理嵌套数组或对象时,你可以指定用于确定唯一性的键。
1$collection = collect([ 2 ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'], 3 ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'], 4 ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'], 5 ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'], 6 ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'], 7]); 8 9$unique = $collection->unique('brand');10 11$unique->values()->all();12 13/*14 [15 ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],16 ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],17 ]18*/
最后,你还可以向 unique 方法传递自己的闭包,以指定哪个值应该确定项目的唯一性。
1$unique = $collection->unique(function (array $item) { 2 return $item['brand'].$item['type']; 3}); 4 5$unique->values()->all(); 6 7/* 8 [ 9 ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],10 ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],11 ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],12 ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],13 ]14*/
unique 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 uniqueStrict 方法进行“严格”比较过滤。
使用 Eloquent 集合 时,此方法的行为会发生改变。
uniqueStrict()
此方法具有与 unique 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
unless()
unless 方法将在传给该方法的第一个参数的计算结果不为 true 时执行给定的回调。集合实例和传给 unless 方法的第一个参数将提供给闭包。
1$collection = collect([1, 2, 3]); 2 3$collection->unless(true, function (Collection $collection, bool $value) { 4 return $collection->push(4); 5}); 6 7$collection->unless(false, function (Collection $collection, bool $value) { 8 return $collection->push(5); 9});10 11$collection->all();12 13// [1, 2, 3, 5]
可以向 unless 方法传递第二个回调。当传给 unless 方法的第一个参数的计算结果为 true 时,将执行第二个回调。
1$collection = collect([1, 2, 3]); 2 3$collection->unless(true, function (Collection $collection, bool $value) { 4 return $collection->push(4); 5}, function (Collection $collection, bool $value) { 6 return $collection->push(5); 7}); 8 9$collection->all();10 11// [1, 2, 3, 5]
关于 unless 的反向操作,请参阅 when 方法。
unlessEmpty()
whenNotEmpty 方法的别名。
unlessNotEmpty()
whenEmpty 方法的别名。
unwrap()
静态 unwrap 方法在适用时从给定值返回集合的底层项目。
1Collection::unwrap(collect('John Doe')); 2 3// ['John Doe'] 4 5Collection::unwrap(['John Doe']); 6 7// ['John Doe'] 8 9Collection::unwrap('John Doe');10 11// 'John Doe'
value()
value 方法从集合的第一个元素中检索给定的值。
1$collection = collect([2 ['product' => 'Desk', 'price' => 200],3 ['product' => 'Speaker', 'price' => 400],4]);5 6$value = $collection->value('price');7 8// 200
values()
values 方法返回一个键已重置为连续整数的新集合。
1$collection = collect([ 2 10 => ['product' => 'Desk', 'price' => 200], 3 11 => ['product' => 'Speaker', 'price' => 400], 4]); 5 6$values = $collection->values(); 7 8$values->all(); 9 10/*11 [12 0 => ['product' => 'Desk', 'price' => 200],13 1 => ['product' => 'Speaker', 'price' => 400],14 ]15*/
when()
when 方法将在传给该方法的第一个参数的计算结果为 true 时执行给定的回调。集合实例和传给 when 方法的第一个参数将提供给闭包。
1$collection = collect([1, 2, 3]); 2 3$collection->when(true, function (Collection $collection, bool $value) { 4 return $collection->push(4); 5}); 6 7$collection->when(false, function (Collection $collection, bool $value) { 8 return $collection->push(5); 9});10 11$collection->all();12 13// [1, 2, 3, 4]
可以向 when 方法传递第二个回调。当传给 when 方法的第一个参数的计算结果为 false 时,将执行第二个回调。
1$collection = collect([1, 2, 3]); 2 3$collection->when(false, function (Collection $collection, bool $value) { 4 return $collection->push(4); 5}, function (Collection $collection, bool $value) { 6 return $collection->push(5); 7}); 8 9$collection->all();10 11// [1, 2, 3, 5]
关于 when 的反向操作,请参阅 unless 方法。
whenEmpty()
whenEmpty 方法将在集合为空时执行给定的回调。
1$collection = collect(['Michael', 'Tom']); 2 3$collection->whenEmpty(function (Collection $collection) { 4 return $collection->push('Adam'); 5}); 6 7$collection->all(); 8 9// ['Michael', 'Tom']10 11$collection = collect();12 13$collection->whenEmpty(function (Collection $collection) {14 return $collection->push('Adam');15});16 17$collection->all();18 19// ['Adam']
可以向 whenEmpty 方法传递第二个闭包,当集合不为空时将执行该闭包。
1$collection = collect(['Michael', 'Tom']); 2 3$collection->whenEmpty(function (Collection $collection) { 4 return $collection->push('Adam'); 5}, function (Collection $collection) { 6 return $collection->push('Taylor'); 7}); 8 9$collection->all();10 11// ['Michael', 'Tom', 'Taylor']
关于 whenEmpty 的反向操作,请参阅 whenNotEmpty 方法。
whenNotEmpty()
whenNotEmpty 方法将在集合不为空时执行给定的回调。
1$collection = collect(['Michael', 'Tom']); 2 3$collection->whenNotEmpty(function (Collection $collection) { 4 return $collection->push('Adam'); 5}); 6 7$collection->all(); 8 9// ['Michael', 'Tom', 'Adam']10 11$collection = collect();12 13$collection->whenNotEmpty(function (Collection $collection) {14 return $collection->push('Adam');15});16 17$collection->all();18 19// []
可以向 whenNotEmpty 方法传递第二个闭包,当集合为空时将执行该闭包。
1$collection = collect(); 2 3$collection->whenNotEmpty(function (Collection $collection) { 4 return $collection->push('Adam'); 5}, function (Collection $collection) { 6 return $collection->push('Taylor'); 7}); 8 9$collection->all();10 11// ['Taylor']
关于 whenNotEmpty 的反向操作,请参阅 whenEmpty 方法。
where()
where 方法通过给定的键/值对过滤集合。
1$collection = collect([ 2 ['product' => 'Desk', 'price' => 200], 3 ['product' => 'Chair', 'price' => 100], 4 ['product' => 'Bookcase', 'price' => 150], 5 ['product' => 'Door', 'price' => 100], 6]); 7 8$filtered = $collection->where('price', 100); 9 10$filtered->all();11 12/*13 [14 ['product' => 'Chair', 'price' => 100],15 ['product' => 'Door', 'price' => 100],16 ]17*/
where 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereStrict 方法进行“严格”比较过滤,或者使用 whereNull 和 whereNotNull 方法过滤 null 值。
或者,你可以传递比较运算符作为第二个参数。支持的运算符有:'===', '!==', '!=', '==', '=', '<>', '>', '<', '>=', 和 '<='。
1$collection = collect([ 2 ['name' => 'Jim', 'platform' => 'Mac'], 3 ['name' => 'Sally', 'platform' => 'Mac'], 4 ['name' => 'Sue', 'platform' => 'Linux'], 5]); 6 7$filtered = $collection->where('platform', '!=', 'Linux'); 8 9$filtered->all();10 11/*12 [13 ['name' => 'Jim', 'platform' => 'Mac'],14 ['name' => 'Sally', 'platform' => 'Mac'],15 ]16*/
whereStrict()
此方法具有与 where 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
whereBetween()
whereBetween 方法通过确定指定项目值是否在给定范围内来过滤集合。
1$collection = collect([ 2 ['product' => 'Desk', 'price' => 200], 3 ['product' => 'Chair', 'price' => 80], 4 ['product' => 'Bookcase', 'price' => 150], 5 ['product' => 'Pencil', 'price' => 30], 6 ['product' => 'Door', 'price' => 100], 7]); 8 9$filtered = $collection->whereBetween('price', [100, 200]);10 11$filtered->all();12 13/*14 [15 ['product' => 'Desk', 'price' => 200],16 ['product' => 'Bookcase', 'price' => 150],17 ['product' => 'Door', 'price' => 100],18 ]19*/
whereIn()
whereIn 方法从集合中删除不具有包含在给定数组内的指定项目值的元素。
1$collection = collect([ 2 ['product' => 'Desk', 'price' => 200], 3 ['product' => 'Chair', 'price' => 100], 4 ['product' => 'Bookcase', 'price' => 150], 5 ['product' => 'Door', 'price' => 100], 6]); 7 8$filtered = $collection->whereIn('price', [150, 200]); 9 10$filtered->all();11 12/*13 [14 ['product' => 'Desk', 'price' => 200],15 ['product' => 'Bookcase', 'price' => 150],16 ]17*/
whereIn 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereInStrict 方法进行“严格”比较过滤。
whereInStrict()
此方法具有与 whereIn 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
whereInstanceOf()
whereInstanceOf 方法按给定的类类型过滤集合。
1use App\Models\User; 2use App\Models\Post; 3 4$collection = collect([ 5 new User, 6 new User, 7 new Post, 8]); 9 10$filtered = $collection->whereInstanceOf(User::class);11 12$filtered->all();13 14// [App\Models\User, App\Models\User]
whereNotBetween()
whereNotBetween 方法通过确定指定项目值是否在给定范围之外来过滤集合。
1$collection = collect([ 2 ['product' => 'Desk', 'price' => 200], 3 ['product' => 'Chair', 'price' => 80], 4 ['product' => 'Bookcase', 'price' => 150], 5 ['product' => 'Pencil', 'price' => 30], 6 ['product' => 'Door', 'price' => 100], 7]); 8 9$filtered = $collection->whereNotBetween('price', [100, 200]);10 11$filtered->all();12 13/*14 [15 ['product' => 'Chair', 'price' => 80],16 ['product' => 'Pencil', 'price' => 30],17 ]18*/
whereNotIn()
whereNotIn 方法从集合中删除具有包含在给定数组内的指定项目值的元素。
1$collection = collect([ 2 ['product' => 'Desk', 'price' => 200], 3 ['product' => 'Chair', 'price' => 100], 4 ['product' => 'Bookcase', 'price' => 150], 5 ['product' => 'Door', 'price' => 100], 6]); 7 8$filtered = $collection->whereNotIn('price', [150, 200]); 9 10$filtered->all();11 12/*13 [14 ['product' => 'Chair', 'price' => 100],15 ['product' => 'Door', 'price' => 100],16 ]17*/
whereNotIn 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereNotInStrict 方法进行“严格”比较过滤。
whereNotInStrict()
此方法具有与 whereNotIn 方法相同的签名;但是,所有值都使用“严格”比较进行比较。
whereNotNull()
whereNotNull 方法返回集合中给定键不为 null 的项目。
1$collection = collect([ 2 ['name' => 'Desk'], 3 ['name' => null], 4 ['name' => 'Bookcase'], 5 ['name' => 0], 6 ['name' => ''], 7]); 8 9$filtered = $collection->whereNotNull('name');10 11$filtered->all();12 13/*14 [15 ['name' => 'Desk'],16 ['name' => 'Bookcase'],17 ['name' => 0],18 ['name' => ''],19 ]20*/
whereNull()
whereNull 方法返回集合中给定键为 null 的项目。
1$collection = collect([ 2 ['name' => 'Desk'], 3 ['name' => null], 4 ['name' => 'Bookcase'], 5 ['name' => 0], 6 ['name' => ''], 7]); 8 9$filtered = $collection->whereNull('name');10 11$filtered->all();12 13/*14 [15 ['name' => null],16 ]17*/
wrap()
静态 wrap 方法在适用时将给定值包装在集合中。
1use Illuminate\Support\Collection; 2 3$collection = Collection::wrap('John Doe'); 4 5$collection->all(); 6 7// ['John Doe'] 8 9$collection = Collection::wrap(['John Doe']);10 11$collection->all();12 13// ['John Doe']14 15$collection = Collection::wrap(collect('John Doe'));16 17$collection->all();18 19// ['John Doe']
zip()
zip 方法将给定数组的值与原始集合对应索引处的值合并在一起。
1$collection = collect(['Chair', 'Desk']);2 3$zipped = $collection->zip([100, 200]);4 5$zipped->all();6 7// [['Chair', 100], ['Desk', 200]]
高阶消息
集合还支持“高阶消息”,这是对集合执行常见操作的快捷方式。提供高阶消息的集合方法有:average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, 和 unique。
每个高阶消息都可以作为集合实例上的动态属性进行访问。例如,让我们使用 each 高阶消息来调用集合中每个对象的方法:
1use App\Models\User;2 3$users = User::where('votes', '>', 500)->get();4 5$users->each->markAsVip();
同样,我们可以使用 sum 高阶消息来获取用户集合的总“投票”数:
1$users = User::where('group', 'Development')->get();2 3return $users->sum->votes;
惰性集合
简介
在深入了解 Laravel 的惰性集合之前,花点时间熟悉一下 PHP 生成器。
为了补充已经非常强大的 Collection 类,LazyCollection 类利用 PHP 的 生成器,让你能够处理非常大的数据集,同时保持较低的内存占用。
例如,假设你的应用程序需要处理一个数千兆字节的日志文件,同时利用 Laravel 的集合方法来解析日志。与其一次将整个文件读取到内存中,不如使用惰性集合,在任何给定时间仅在内存中保留文件的一小部分。
1use App\Models\LogEntry; 2use Illuminate\Support\LazyCollection; 3 4LazyCollection::make(function () { 5 $handle = fopen('log.txt', 'r'); 6 7 while (($line = fgets($handle)) !== false) { 8 yield $line; 9 }10 11 fclose($handle);12})->chunk(4)->map(function (array $lines) {13 return LogEntry::fromLines($lines);14})->each(function (LogEntry $logEntry) {15 // Process the log entry...16});
或者,假设你需要遍历 10,000 个 Eloquent 模型。使用传统的 Laravel 集合时,所有 10,000 个 Eloquent 模型必须同时加载到内存中。
1use App\Models\User;2 3$users = User::all()->filter(function (User $user) {4 return $user->id > 500;5});
然而,查询构建器的 cursor 方法返回一个 LazyCollection 实例。这允许你仍然只对数据库运行单个查询,但一次只在内存中保留一个 Eloquent 模型。在此示例中,filter 回调直到我们实际单独遍历每个用户时才执行,从而大幅减少了内存使用。
1use App\Models\User;2 3$users = User::cursor()->filter(function (User $user) {4 return $user->id > 500;5});6 7foreach ($users as $user) {8 echo $user->id;9}
创建惰性集合
要创建惰性集合实例,你应该将 PHP 生成器函数传递给集合的 make 方法。
1use Illuminate\Support\LazyCollection; 2 3LazyCollection::make(function () { 4 $handle = fopen('log.txt', 'r'); 5 6 while (($line = fgets($handle)) !== false) { 7 yield $line; 8 } 9 10 fclose($handle);11});
Enumerable 契约
Collection 类上几乎所有可用的方法在 LazyCollection 类上也可用。这两个类都实现了 Illuminate\Support\Enumerable 契约,该契约定义了以下方法:
all average avg chunk chunkWhile collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys dump duplicates duplicatesStrict each eachSpread every except filter first firstOrFail firstWhere flatMap flatten flip forPage get groupBy has implode intersect intersectAssoc intersectByKeys isEmpty isNotEmpty join keyBy keys last macro make map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode nth only pad partition pipe pluck random reduce reject replace replaceRecursive reverse search shuffle skip slice sole some sort sortBy sortByDesc sortKeys sortKeysDesc split sum take tap times toArray toJson union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween wrap zip
改变集合的方法(如 shift, pop, prepend 等)在 LazyCollection 类上不可用。
惰性集合方法
除了 Enumerable 契约中定义的方法外,LazyCollection 类还包含以下方法:
takeUntilTimeout()
takeUntilTimeout 方法返回一个新的惰性集合,该集合将枚举值直到指定的时间。在该时间之后,集合将停止枚举。
1$lazyCollection = LazyCollection::times(INF) 2 ->takeUntilTimeout(now()->plus(minutes: 1)); 3 4$lazyCollection->each(function (int $number) { 5 dump($number); 6 7 sleep(1); 8}); 9 10// 111// 212// ...13// 5814// 59
为了说明此方法的用法,想象一个应用程序使用游标从数据库提交发票。你可以定义一个每 15 分钟运行一次的 定时任务,并且只处理发票最多 14 分钟。
1use App\Models\Invoice;2use Illuminate\Support\Carbon;3 4Invoice::pending()->cursor()5 ->takeUntilTimeout(6 Carbon::createFromTimestamp(LARAVEL_START)->add(14, 'minutes')7 )8 ->each(fn (Invoice $invoice) => $invoice->submit());
tapEach()
虽然 each 方法会立即为集合中的每个项目调用给定的回调,但 tapEach 方法仅在项目从列表中一个接一个地取出时才调用给定的回调。
1// Nothing has been dumped so far... 2$lazyCollection = LazyCollection::times(INF)->tapEach(function (int $value) { 3 dump($value); 4}); 5 6// Three items are dumped... 7$array = $lazyCollection->take(3)->all(); 8 9// 110// 211// 3
throttle()
throttle 方法将对惰性集合进行限流,使得每个值在指定的秒数后返回。此方法特别适用于你可能与限制传入请求速率的外部 API 交互的情况。
1use App\Models\User;2 3User::where('vip', true)4 ->cursor()5 ->throttle(seconds: 1)6 ->each(function (User $user) {7 // Call external API...8 });
remember()
remember 方法返回一个新的惰性集合,该集合将记住已枚举的任何值,并且在后续集合枚举中不会再次检索它们。
1// No query has been executed yet... 2$users = User::cursor()->remember(); 3 4// The query is executed... 5// The first 5 users are hydrated from the database... 6$users->take(5)->all(); 7 8// First 5 users come from the collection's cache... 9// The rest are hydrated from the database...10$users->take(20)->all();
withHeartbeat()
withHeartbeat 方法允许你在枚举惰性集合时以固定的时间间隔执行回调。这对于需要定期维护任务的长耗时操作特别有用,例如延长锁或发送进度更新。
1use Carbon\CarbonInterval; 2use Illuminate\Support\Facades\Cache; 3 4$lock = Cache::lock('generate-reports', seconds: 60 * 5); 5 6if ($lock->get()) { 7 try { 8 Report::where('status', 'pending') 9 ->lazy()10 ->withHeartbeat(11 CarbonInterval::minutes(4),12 fn () => $lock->extend(CarbonInterval::minutes(5))13 )14 ->each(fn ($report) => $report->process());15 } finally {16 $lock->release();17 }18}