集合
简介
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();