集合
简介
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 方法将给定的数组或集合与原始集合合并。如果给定项中的字符串键与原始集合中的字符串键匹配,则给定项的值将覆盖原始集合中的值。
$collection = collect(['product_id' => 1, 'price' => 100]); $merged = $collection->merge(['price' => 200, 'discount' => false]); $merged->all(); // ['product_id' => 1, 'price' => 200, 'discount' => false]
如果给定项的键是数字,则这些值将附加到集合的末尾。
$collection = collect(['Desk', 'Chair']); $merged = $collection->merge(['Bookcase', 'Door']); $merged->all(); // ['Desk', 'Chair', 'Bookcase', 'Door']
mergeRecursive()
mergeRecursive 方法将给定的数组或集合与原始集合递归合并。如果给定项中的字符串键与原始集合中的字符串键匹配,则这些键的值将合并到一个数组中,并且这是递归完成的。
$collection = collect(['product_id' => 1, 'price' => 100]); $merged = $collection->mergeRecursive([ 'product_id' => 2, 'price' => 200, 'discount' => false]); $merged->all(); // ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
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 方法将集合减少为值数组,并将每次迭代的结果传递到后续迭代中。此方法类似于 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 方法会跳过集合中的元素,直到给定的回调返回 false。一旦回调返回 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。一旦回调返回 false,集合中剩余的所有元素将作为一个新的集合返回。
$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;});
你可以选择传递第二个 “step” 值,它决定了每个块的第一个元素之间的距离。
$collection = collect([1, 2, 3, 4, 5]); $chunks = $collection->sliding(3, step: 2); $chunks->toArray(); // [[1, 2, 3], [3, 4, 5]]
sole()
sole 方法返回集合中通过给定真值测试的第一个元素,但前提是真值测试恰好匹配一个元素。
collect([1, 2, 3, 4])->sole(function (int $value, int $key) { return $value === 2;}); // 2
你也可以向 sole 方法传递一个键/值对,该方法将返回集合中与给定对匹配的第一个元素,但前提是恰好只有一个元素匹配。
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100],]); $collection->sole('product', 'Chair'); // ['product' => 'Chair', 'price' => 100]
或者,你也可以在不带参数的情况下调用 sole 方法,如果集合中只有一个元素,则获取该元素。
$collection = collect([ ['product' => 'Desk', 'price' => 200],]); $collection->sole(); // ['product' => 'Desk', 'price' => 200]
如果集合中没有应该由 sole 方法返回的元素,则会抛出 \Illuminate\Collections\ItemNotFoundException 异常。如果应该返回多个元素,则会抛出 \Illuminate\Collections\MultipleItemsFoundException 异常。
some()
是 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 方法接受 排序标志 作为其第二个参数。
$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”进入集合并对元素执行某些操作,而不会影响集合本身。然后,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()
当传递给该方法的第一个参数的计算结果为 true 时,when 方法将执行给定的回调。集合实例和传递给 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; }});
可枚举契约
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();