集合
简介
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]);
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']
通常,您应该在 服务提供者 的 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
实例,允许您在必要时保留集合的原始副本
after all average avg before chunk chunkWhile collapse collect combine concat contains containsOneItem containsStrict count countBy crossJoin dd diff diffAssoc diffAssocUsing diffKeys doesntContain dot dump duplicates duplicatesStrict each eachSpread ensure every except filter first firstOrFail firstWhere flatMap flatten flip forget forPage get groupBy has hasAny implode intersect intersectAssoc 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 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
$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
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]
collect()
collect
方法返回一个新的 Collection
实例,其中包含集合中当前的项目。
$collectionA = collect([1, 2, 3]); $collectionB = $collectionA->collect(); $collectionB->all(); // [1, 2, 3]
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
方法将给定 array
或集合的值追加到另一个集合的末尾。
$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
您还可以将键/值对传递给 contains
方法,这将确定集合中是否存在给定的对。
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100],]); $collection->contains('product', 'Bookcase'); // false
contains
方法在检查项目值时使用“宽松”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 containsStrict
方法使用“严格”比较进行筛选。
有关 contains
的逆运算,请参阅 doesntContain 方法。
containsOneItem()
containsOneItem
方法确定集合是否包含单个项目。
collect([])->containsOneItem(); // false collect(['1'])->containsOneItem(); // true collect(['1', '2'])->containsOneItem(); // false
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
方法,以根据自定义值计算所有项目。
$counted = $collection->countBy(function (string $email) { return substr(strrchr($email, "@"), 1);}); $counted->all(); // ['gmail.com' => 2, 'yahoo.com' => 1]
crossJoin()
crossJoin
方法在给定的数组或集合之间交叉连接集合的值,返回包含所有可能排列的笛卡尔积。
$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(); /* Collection { #items: array:2 [ 0 => "John Doe" 1 => "Jane Doe" ] }*/
如果您不想停止脚本的执行,请改用 dump
方法。
diff()
diff
方法根据其值将集合与另一个集合或普通 PHP array
进行比较。此方法将返回原始集合中不存在于给定集合中的值。
$collection = collect([1, 2, 3, 4, 5]); $diff = $collection->diff([2, 4, 6, 8]); $diff->all(); // [1, 3, 5]
使用 Eloquent 集合 时,此方法的行为会发生改变。
diffAssoc()
diffAssoc
方法根据其键和值将集合与另一个集合或普通 PHP array
进行比较。此方法将返回原始集合中不存在于给定集合中的键/值对。
$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]
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]
回调必须是一个比较函数,该函数返回小于、等于或大于零的整数。有关更多信息,请参阅 PHP 文档中关于 array_diff_uassoc
的内容,该函数是 diffAssocUsing
方法在内部使用的 PHP 函数。
diffKeys()
diffKeys
方法根据其键将集合与另一个集合或普通 PHP array
进行比较。此方法将返回原始集合中不存在于给定集合中的键/值对。
$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
方法确定集合是否不包含给定项目。您可以将闭包传递给 doesntContain
方法,以确定集合中是否存在与给定真值测试不匹配的元素。
$collection = collect([1, 2, 3, 4, 5]); $collection->doesntContain(function (int $value, int $key) { return $value < 5;}); // false
或者,您可以将字符串传递给 doesntContain
方法,以确定集合是否不包含给定的项目值。
$collection = collect(['name' => 'Desk', 'price' => 100]); $collection->doesntContain('Table'); // true $collection->doesntContain('Desk'); // false
您还可以将键/值对传递给 doesntContain
方法,这将确定集合中是否存在给定的对。
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100],]); $collection->doesntContain('product', 'Bookcase'); // true
doesntContain
方法在检查项目值时使用“宽松”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。
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(); /* Collection { #items: 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([]); $employees->duplicates('position'); // [2 => 'Developer']
duplicatesStrict()
此方法与 duplicates
方法具有相同的签名;但是,所有值都使用“严格”比较进行比较。
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; }});
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]);
还可以指定原始类型,例如 string
、int
、float
、bool
和 array
。
return $collection->ensure('int');
ensure
方法不能保证以后不会将不同类型的元素添加到集合中。
every()
every
方法可用于验证集合的所有元素是否都通过给定的真值测试。
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 集合 时,此方法的行为会发生改变。
filter()
filter
方法使用给定的回调筛选集合,只保留通过给定真值测试的项目。
$collection = collect([1, 2, 3, 4]); $filtered = $collection->filter(function (int $value, int $key) { return $value > 2;}); $filtered->all(); // [3, 4]
如果未提供回调,则将删除集合中等于 false
的所有条目。
$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;}); // Throws ItemNotFoundException...
您也可以在不带任何参数的情况下调用 firstOrFail
方法以获取集合中的第一个元素。如果集合为空,则将抛出 Illuminate\Support\ItemNotFoundException
异常。
collect([])->firstOrFail(); // Throws 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]
您还可以使用比较运算符调用 firstWhere
方法。
$collection->firstWhere('age', '>=', 18); // ['name' => 'Diego', 'age' => 23]
与 where 方法一样,您可以将一个参数传递给 firstWhere
方法。在这种情况下,firstWhere
方法将返回给定项目键的值为“真值”的第一个项目。
$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
方法。
$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'], ]*/
在此示例中,在不提供深度的情况下调用 flatten
也会展平嵌套数组,从而导致 ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']
。提供深度允许您指定嵌套数组将展平的级别数。
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']); // Forget a single key...$collection->forget('name'); // ['framework' => 'laravel'] // Forget multiple keys...$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]
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
您甚至可以将回调作为方法的默认值传递。如果指定的键不存在,则将返回回调的结果。
$collection->get('email', function () {});
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'], ], ]*/
您可以传递回调而不是字符串 key
。回调应该返回您希望作为其键进行分组的值。
$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']], ], ],];*/
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
方法从原始集合中删除在给定的 array
或集合中不存在的任何值。生成的集合将保留原始集合的键。
$collection = collect(['Desk', 'Sofa', 'Chair']); $intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']); $intersect->all(); // [0 => 'Desk', 2 => 'Chair']
使用 Eloquent 集合 时,此方法的行为会发生改变。
intersectAssoc()
intersectAssoc
方法将原始集合与另一个集合或 array
进行比较,返回所有给定集合中都存在的键/值对。
$collection = collect([ 'color' => 'red', 'size' => 'M', 'material' => 'cotton']); $intersect = $collection->intersectAssoc([ 'color' => 'blue', 'size' => 'M', 'material' => 'polyester']); $intersect->all(); // ['size' => 'M']
intersectByKeys()
intersectByKeys
方法删除原始集合中在给定的 array
或集合中不存在的任何键及其对应值。
$collection = collect([ 'serial' => 'UX301', 'type' => 'screen', 'year' => 2009,]); $intersect = $collection->intersectByKeys([ 'reference' => 'UX404', 'type' => 'tab', 'year' => 2011,]); $intersect->all(); // ['type' => 'screen', 'year' => 2009]
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'], ]*/
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
您也可以在不带任何参数的情况下调用 last
方法以获取集合中的最后一个元素。如果集合为空,则返回 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
类添加方法。有关更多信息,请参阅有关 扩展集合 的文档。
make()
静态 make
方法创建一个新的集合实例。请参阅 创建集合 部分。
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{ /** * Create a new currency instance. */ 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']
mapWithKeys()
mapWithKeys
方法遍历集合并将每个值传递给给定的回调。回调应返回一个包含单个键/值对的关联数组。
$collection = collect([ [ 'name' => 'John', 'department' => 'Sales', ], [ 'name' => 'Jane', 'department' => 'Marketing', ]]); $keyed = $collection->mapWithKeys(function (array $item, int $key) { return [$item['email'] => $item['name']];}); $keyed->all(); /* [ '[email protected]' => 'John', '[email protected]' => '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
方法将给定的数组或集合与原始集合合并。如果给定项目中的字符串键与原始集合中的字符串键匹配,则给定项目的 value 将覆盖原始集合中的 value。
$collection = collect(['product_id' => 1, 'price' => 100]); $merged = $collection->merge(['price' => 200, 'discount' => false]); $merged->all(); // ['product_id' => 1, 'price' => 200, 'discount' => false]
如果给定项目的键是数字,则 value 将追加到集合的末尾。
$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]
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([])->multiply(3); /* [ ['name' => 'User #1', 'email' => '[email protected]'], ['name' => 'User #2', 'email' => '[email protected]'], ['name' => 'User #1', 'email' => '[email protected]'], ['name' => 'User #2', 'email' => '[email protected]'], ['name' => 'User #1', 'email' => '[email protected]'], ['name' => 'User #2', 'email' => '[email protected]'], ]*/
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']
有关 only
的反向操作,请参阅 except 方法。
使用 Eloquent 集合 时,此方法的行为会发生改变。
pad()
pad
方法将使用给定的值填充数组,直到数组达到指定的大小。此方法的行为类似于 array_pad PHP 函数。
要向左填充,您应该指定一个负大小。如果给定大小的绝对值小于或等于数组的长度,则不会进行任何填充。
$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]
percentage()
percentage
方法可用于快速确定通过给定真值测试的集合中项目的百分比。
$collection = collect([1, 1, 2, 2, 2, 3]); $percentage = $collection->percentage(fn ($value) => $value === 1); // 33.33
默认情况下,百分比将四舍五入到小数点后两位。但是,您可以通过向方法提供第二个参数来自定义此行为。
$percentage = $collection->percentage(fn ($value) => $value === 1, precision: 3); // 33.333
pipe()
pipe
方法将集合传递给给定的闭包并返回执行的闭包的结果。
$collection = collect([1, 2, 3]); $piped = $collection->pipe(function (Collection $collection) { return $collection->sum();}); // 6
pipeInto()
pipeInto
方法创建一个给定类的新的实例并将集合传递给构造函数。
class ResourceCollection{ /** * Create a new ResourceCollection instance. */ 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
方法还支持使用“点”表示法检索嵌套值。
$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']
pop()
pop
方法删除并返回集合中的最后一个项目。
$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 - (retrieved randomly)
您可以将整数传递给 random
以指定要随机检索多少个项目。当显式传递要接收的项目数时,始终返回一个项目集合。
$random = $collection->random(3); $random->all(); // [2, 4, 5] - (retrieved randomly)
如果集合实例的项目少于请求的项目,则 random
方法将抛出 InvalidArgumentException
。
random
方法还接受闭包,该闭包将接收当前集合实例。
use Illuminate\Support\Collection; $random = $collection->random(fn (Collection $items) => min(10, count($items))); $random->all(); // [1, 2, 3, 4, 5] - (retrieved randomly)
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
;但是,您可以通过将第二个参数传递给 reduce
来指定其初始值。
$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, int $key) use ($ratio) { return $carry + ($value * $ratio[$key]);}); // 4264
reduceSpread()
reduceSpread
方法将集合缩减为一个 value 数组,并将每次迭代的结果传递到后续迭代中。此方法类似于 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());
reject()
reject
方法使用给定的闭包过滤集合。如果应从结果集合中删除该项目,则闭包应返回 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
;但是,除了覆盖具有字符串键的匹配项目外,replace
方法还将覆盖集合中具有匹配数字键的项目。
$collection = collect(['Taylor', 'Abigail', 'James']); $replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']); $replaced->all(); // ['Taylor', 'Victoria', 'James', 'Finn']
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
搜索是使用“宽松”比较完成的,这意味着具有整数值的字符串将被视为等于相同值的整数。要使用“严格”比较,请将 true
作为第二个参数传递给该方法。
collect([2, 4, 6, 8])->search('4', strict: true); // false
或者,您可以提供自己的闭包来搜索通过给定真值测试的第一个项目
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
,然后将集合中剩余的项作为新集合实例返回。
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(function (int $item) { return $item >= 3;}); $subset->all(); // [3, 4]
您也可以向 skipUntil
方法传递一个简单值,以跳过所有项,直到找到给定的值。
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(3); $subset->all(); // [3, 4]
如果未找到给定的值或回调函数从未返回 true
,则 skipUntil
方法将返回一个空集合。
skipWhile()
skipWhile
方法会跳过集合中的项,只要给定的回调函数返回 true
,然后将集合中剩余的项作为新集合返回。
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipWhile(function (int $item) { return $item <= 3;}); $subset->all(); // [4]
如果回调函数从未返回 false
,则 skipWhile
方法将返回一个空集合。
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]
默认情况下,返回的切片会保留键。如果您不希望保留原始键,可以使用 values
方法重新索引它们。
sliding()
sliding
方法返回一个新的集合,其中包含表示集合中项的“滑动窗口”视图的块。
$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;});
您可以选择传递第二个“步长”值,该值确定每个块的第一个项之间的距离。
$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()
contains
方法的别名。
sort()
sort
方法对集合进行排序。排序后的集合会保留原始数组键,因此在以下示例中,我们将使用 values
方法将键重置为连续编号的索引。
$collection = collect([5, 3, 1, 2, 4]); $sorted = $collection->sort(); $sorted->values()->all(); // [1, 2, 3, 4, 5]
如果您的排序需求更复杂,您可以向 sort
传递一个回调函数,并使用您自己的算法。请参阅 PHP 文档中关于 uasort
的内容,该方法是集合的 sort
方法内部调用的方法。
如果您需要对嵌套数组或对象的集合进行排序,请参阅 sortBy
和 sortByDesc
方法。
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 标志 作为其第二个参数。
$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']], ]*/
如果您想根据多个属性对集合进行排序,可以向 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
方法并反转您的比较。
sortKeys()
sortKeys
方法根据底层关联数组的键对集合进行排序。
$collection = collect([ 'id' => 22345, 'first' => 'John', 'last' => 'Doe',]); $sorted = $collection->sortKeys(); $sorted->all(); /* [ 'first' => 'John', 'id' => 22345, 'last' => 'Doe', ]*/
sortKeysDesc()
此方法与 sortKeys
方法具有相同的签名,但会按相反的顺序对集合进行排序。
sortKeysUsing()
sortKeysUsing
方法使用回调函数根据底层关联数组的键对集合进行排序。
$collection = collect([ 'ID' => 22345, 'first' => 'John', 'last' => 'Doe',]); $sorted = $collection->sortKeysUsing('strnatcasecmp'); $sorted->all(); /* [ 'first' => 'John', 'ID' => 22345, 'last' => 'Doe', ]*/
回调函数必须是一个比较函数,该函数返回一个小于、等于或大于零的整数。有关更多信息,请参阅 PHP 文档中关于 uksort
的内容,该方法是 sortKeysUsing
方法内部调用的 PHP 函数。
splice()
splice
方法删除并返回从指定索引开始的项切片。
$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2); $chunk->all(); // [3, 4, 5] $collection->all(); // [1, 2]
您可以传递第二个参数来限制结果集合的大小。
$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2, 1); $chunk->all(); // [3] $collection->all(); // [1, 2, 4, 5]
此外,您可以传递第三个参数,其中包含要替换从集合中删除的项的新项。
$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()
split
方法将集合分成给定的组数。
$collection = collect([1, 2, 3, 4, 5]); $groups = $collection->split(3); $groups->all(); // [[1, 2], [3, 4], [5]]
splitIn()
splitIn
方法将集合分成给定的组数,在将余数分配给最后一组之前,先完全填充非终端组。
$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()
sum
方法返回集合中所有项的总和。
collect([1, 2, 3, 4, 5])->sum(); // 15
如果集合包含嵌套数组或对象,则应传递一个键,该键将用于确定要对哪些值求和。
$collection = collect([ ['name' => 'JavaScript: The Good Parts', 'pages' => 176], ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],]); $collection->sum('pages'); // 1272
此外,您可以传递自己的闭包来确定要对集合的哪些值求和。
$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()
take
方法返回一个包含指定数量项的新集合。
$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(3); $chunk->all(); // [0, 1, 2]
您也可以传递一个负整数,以从集合的末尾获取指定数量的项。
$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(-2); $chunk->all(); // [4, 5]
takeUntil()
takeUntil
方法返回集合中的项,直到给定的回调函数返回 true
。
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(function (int $item) { return $item >= 3;}); $subset->all(); // [1, 2]
您也可以向 takeUntil
方法传递一个简单值,以获取直到找到给定值为止的项。
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(3); $subset->all(); // [1, 2]
如果未找到给定的值或回调函数从未返回 true
,则 takeUntil
方法将返回集合中的所有项。
takeWhile()
takeWhile
方法返回集合中的项,直到给定的回调函数返回 false
。
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeWhile(function (int $item) { return $item < 3;}); $subset->all(); // [1, 2]
如果回调函数从未返回 false
,则 takeWhile
方法将返回集合中的所有项。
tap()
tap
方法将集合传递给给定的回调函数,允许您在特定点“点击”集合并对项执行某些操作,而不会影响集合本身。然后,集合将由 tap
方法返回。
collect([2, 4, 3, 1, 5]) ->sort() ->tap(function (Collection $collection) { Log::debug('Values after sorting', $collection->values()->all()); }) ->shift(); // 1
times()
静态 times
方法通过在指定次数内调用给定的闭包来创建一个新的集合。
$collection = Collection::times(10, function (int $number) { return $number * 9;}); $collection->all(); // [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
toArray()
toArray
方法将集合转换为一个普通的 PHP array
。如果集合的值是 Eloquent 模型,则这些模型也将转换为数组。
$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toArray(); /* [ ['name' => 'Desk', 'price' => 200], ]*/
toArray
还会将集合中所有作为 Arrayable
实例的嵌套对象转换为数组。如果您想获取集合底层的原始数组,请改用 all
方法。
toJson()
toJson
方法将集合转换为 JSON 序列化字符串。
$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toJson(); // '{"name":"Desk", "price":200}'
transform()
transform
方法迭代集合并使用集合中的每个项调用给定的回调函数。集合中的项将被回调函数返回的值替换。
$collection = collect([1, 2, 3, 4, 5]); $collection->transform(function (int $item, int $key) { return $item * 2;}); $collection->all(); // [2, 4, 6, 8, 10]
与大多数其他集合方法不同,transform
会修改集合本身。如果您希望创建一个新的集合,请使用 map
方法。
undot()
undot
方法扩展使用“点”表示法的单维集合,使其成为多维集合。
$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()
union
方法将给定的数组添加到集合中。如果给定的数组包含原始集合中已存在的键,则将优先使用原始集合的值。
$collection = collect([1 => ['a'], 2 => ['b']]); $union = $collection->union([3 => ['c'], 1 => ['d']]); $union->all(); // [1 => ['a'], 2 => ['b'], 3 => ['c']]
unique()
unique
方法返回集合中所有唯一的项。返回的集合会保留原始数组键,因此在以下示例中,我们将使用 values
方法将键重置为连续编号的索引。
$collection = collect([1, 1, 2, 2, 3, 4, 2]); $unique = $collection->unique(); $unique->values()->all(); // [1, 2, 3, 4]
在处理嵌套数组或对象时,您可以指定用于确定唯一性的键。
$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'], ]*/
最后,您还可以将自己的闭包传递给 unique
方法,以指定哪个值应确定项的唯一性。
$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'], ]*/
unique
方法在检查项值时使用“宽松”比较,这意味着具有整数值的字符串将被视为与相同值的整数相等。使用 uniqueStrict
方法使用“严格”比较进行过滤。
使用 Eloquent 集合 时,此方法的行为会发生变化。
uniqueStrict()
此方法与 unique
方法具有相同的签名;但是,所有值都使用“严格”比较进行比较。
unless()
unless
方法将在传递给方法的第一个参数计算结果为 true
时执行给定的回调函数。
$collection = collect([1, 2, 3]); $collection->unless(true, function (Collection $collection) { return $collection->push(4);}); $collection->unless(false, function (Collection $collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
可以向 unless
方法传递第二个回调函数。当传递给 unless
方法的第一个参数计算结果为 true
时,将执行第二个回调函数。
$collection = collect([1, 2, 3]); $collection->unless(true, function (Collection $collection) { return $collection->push(4);}, function (Collection $collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
有关 unless
的反向操作,请参阅 when
方法。
unlessEmpty()
whenNotEmpty
方法的别名。
unlessNotEmpty()
whenEmpty
方法的别名。
unwrap()
静态 unwrap
方法在适用时从给定值返回集合的底层项。
Collection::unwrap(collect('John Doe')); // ['John Doe'] Collection::unwrap(['John Doe']); // ['John Doe'] Collection::unwrap('John Doe'); // 'John Doe'
value()
value
方法从集合的第一个元素中检索给定的值。
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Speaker', 'price' => 400],]); $value = $collection->value('price'); // 200
values()
values
方法返回一个新的集合,其键重置为连续整数。
$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()
when
方法将在传递给方法的第一个参数计算结果为 true
时执行给定的回调函数。集合实例和传递给 when
方法的第一个参数将提供给闭包。
$collection = collect([1, 2, 3]); $collection->when(true, function (Collection $collection, int $value) { return $collection->push(4);}); $collection->when(false, function (Collection $collection, int $value) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 4]
可以向 when
方法传递第二个回调函数。当传递给 when
方法的第一个参数计算结果为 false
时,将执行第二个回调函数。
$collection = collect([1, 2, 3]); $collection->when(false, function (Collection $collection, int $value) { return $collection->push(4);}, function (Collection $collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
有关 when
的反向操作,请参阅 unless
方法。
whenEmpty()
whenEmpty
方法将在集合为空时执行给定的回调函数。
$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']
可以向 whenEmpty
方法传递第二个闭包,该闭包将在集合不为空时执行。
$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']
有关 whenEmpty
的反向操作,请参阅 whenNotEmpty
方法。
whenNotEmpty()
whenNotEmpty
方法将在集合不为空时执行给定的回调函数。
$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(); // []
可以向 whenNotEmpty
方法传递第二个闭包,该闭包将在集合为空时执行。
$collection = collect(); $collection->whenNotEmpty(function (Collection $collection) { return $collection->push('adam');}, function (Collection $collection) { return $collection->push('taylor');}); $collection->all(); // ['taylor']
有关 whenNotEmpty
的反向操作,请参阅 whenEmpty
方法。
where()
where
方法根据给定的键/值对过滤集合。
$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], ]*/
where
方法在检查项目值时使用“宽松”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereStrict
方法使用“严格”比较进行过滤。
可选地,您可以将比较运算符作为第二个参数传递。支持的运算符有:'===', '!==', '!=', '==', '=', '<>', '>', '<', '>=', 和 '<='
$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()
此方法与 where
方法具有相同的签名;但是,所有值都使用“严格”比较进行比较。
whereBetween()
whereBetween
方法通过确定指定项目值是否在给定范围内来过滤集合。
$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()
whereIn
方法删除集合中没有指定项目值包含在给定数组中的元素。
$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], ]*/
whereIn
方法在检查项目值时使用“宽松”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereInStrict
方法使用“严格”比较进行过滤。
whereInStrict()
此方法与 whereIn
方法具有相同的签名;但是,所有值都使用“严格”比较进行比较。
whereInstanceOf()
whereInstanceOf
方法根据给定的类类型过滤集合。
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()
whereNotBetween
方法通过确定指定项目值是否在给定范围之外来过滤集合。
$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()
whereNotIn
方法删除集合中具有指定项目值包含在给定数组中的元素。
$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], ]*/
whereNotIn
方法在检查项目值时使用“宽松”比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereNotInStrict
方法使用“严格”比较进行过滤。
whereNotInStrict()
此方法与 whereNotIn
方法具有相同的签名;但是,所有值都使用“严格”比较进行比较。
whereNotNull()
whereNotNull
方法返回集合中给定键不为 null
的项目。
$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'],]); $filtered = $collection->whereNotNull('name'); $filtered->all(); /* [ ['name' => 'Desk'], ['name' => 'Bookcase'], ]*/
whereNull()
whereNull
方法返回集合中给定键为 null
的项目。
$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'],]); $filtered = $collection->whereNull('name'); $filtered->all(); /* [ ['name' => null], ]*/
wrap()
静态 wrap
方法在适用时将给定值包装在集合中。
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()
zip
方法将给定数组的值与原始集合中对应索引处的值合并。
$collection = collect(['Chair', 'Desk']); $zipped = $collection->zip([100, 200]); $zipped->all(); // [['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
高阶消息在集合中的每个对象上调用一个方法。
use App\Models\User; $users = User::where('votes', '>', 500)->get(); $users->each->markAsVip();
同样,我们可以使用 sum
高阶消息收集用户集合的“投票”总数。
$users = User::where('group', 'Development')->get(); return $users->sum->votes;
惰性集合
简介
在进一步了解 Laravel 的惰性集合之前,请花一些时间熟悉 PHP 生成器。
为了补充功能强大的 Collection
类,LazyCollection
类利用 PHP 的 生成器,使您能够处理非常大的数据集,同时保持较低的内存使用量。
例如,假设您的应用程序需要处理一个多 GB 的日志文件,同时利用 Laravel 的集合方法来解析日志。惰性集合可以不用一次将整个文件读入内存,而是在给定时间仅将文件的一小部分保留在内存中。
use App\Models\LogEntry;use Illuminate\Support\LazyCollection; LazyCollection::make(function () { $handle = fopen('log.txt', 'r'); while (($line = fgets($handle)) !== false) { yield $line; }})->chunk(4)->map(function (array $lines) { return LogEntry::fromLines($lines);})->each(function (LogEntry $logEntry) { // Process the log entry...});
或者,假设您需要遍历 10,000 个 Eloquent 模型。当使用传统的 Laravel 集合时,所有 10,000 个 Eloquent 模型必须同时加载到内存中。
use App\Models\User; $users = User::all()->filter(function (User $user) { return $user->id > 500;});
但是,查询构建器的 cursor
方法返回一个 LazyCollection
实例。这允许您仍然只对数据库运行一个查询,并且一次只将一个 Eloquent 模型加载到内存中。在此示例中,filter
回调直到我们实际遍历每个用户时才会执行,从而大幅减少了内存使用量。
use App\Models\User; $users = User::cursor()->filter(function (User $user) { return $user->id > 500;}); foreach ($users as $user) { echo $user->id;}
创建惰性集合
要创建惰性集合实例,您应该将 PHP 生成器函数传递给集合的 make
方法。
use Illuminate\Support\LazyCollection; LazyCollection::make(function () { $handle = fopen('log.txt', 'r'); while (($line = fgets($handle)) !== false) { yield $line; }});
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 whereNotIn whereNotInStrict wrap zip
修改集合的方法(例如 shift
、pop
、prepend
等)在 LazyCollection
类中**不可用**。
惰性集合方法
除了 Enumerable
合同中定义的方法外,LazyCollection
类还包含以下方法
takeUntilTimeout()
takeUntilTimeout
方法返回一个新的惰性集合,该集合将枚举值,直到指定时间。在此时间之后,集合将停止枚举。
$lazyCollection = LazyCollection::times(INF) ->takeUntilTimeout(now()->addMinute()); $lazyCollection->each(function (int $number) { dump($number); sleep(1);}); // 1// 2// ...// 58// 59
为了说明此方法的用法,假设一个应用程序使用游标从数据库提交发票。您可以定义一个 计划任务,该任务每 15 分钟运行一次,并且仅处理最多 14 分钟的发票。
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()
each
方法会立即为集合中的每个项目调用给定的回调,而 tapEach
方法仅在逐个提取项目时调用给定的回调。
// 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()
throttle
方法将限制惰性集合,以便在指定秒数后返回每个值。此方法特别适用于您可能与限制传入请求的外部 API 交互的情况。
use App\Models\User; User::where('vip', true) ->cursor() ->throttle(seconds: 1) ->each(function (User $user) { // Call external API... });
remember()
remember
方法返回一个新的惰性集合,该集合将记住任何已枚举的值,并且在后续集合枚举中不会再次检索它们。
// No query has been executed yet...$users = User::cursor()->remember(); // The query is executed...// The first 5 users are hydrated from the database...$users->take(5)->all(); // First 5 users come from the collection's cache...// The rest are hydrated from the database...$users->take(20)->all();