Collections
Introduction
这Winter\Storm\Support\Collection
类为处理数据数组提供了一个流畅、方便的包装器。例如,查看以下代码。我们将从数组创建一个新的集合实例,运行strtoupper
在每个元素上运行,然后删除所有空元素:
$collection = new Winter\Storm\Support\Collection(['stewie', 'brian', null]);
$collection = $collection
->map(function ($name) {
return strtoupper($name);
})
->reject(function ($name) {
return empty($name);
})
;
这Collection
类允许您链接其方法以执行底层数组的流畅映射和减少。一般来说每Collection
方法返回一个全新的Collection
实例。
创建集合
如上所述,将数组传递给Winter\Storm\Support\Collection
类将为给定数组返回一个新实例。因此,创建一个集合非常简单:
$collection = new Winter\Storm\Support\Collection([1, 2, 3]);
默认情况下,集合数据库模型 总是返回为Collection
实例;但是,请随意使用Collection
在您的应用程序方便的地方上课。
可用方法
对于本文档的其余部分,我们将讨论Collection
班级。请记住,所有这些方法都可以链接起来以流畅地操作底层数组。此外,几乎每个方法都会返回一个新的Collection
例如,允许您在必要时保留集合的原始副本。
您可以从此表中选择任何方法来查看其用法示例:
all average avg chunk collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys dump duplicates duplicatesStrict each filter first firstWhere flatMap flatten flip forget forPage get groupBy has implode intersect intersectByKeys isEmpty isNotEmpty join keyBy keys last map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode nth only pad partition pipe pluck pop prepend pull push put random reduce reject replace replaceRecursive reverse search shift shuffle skip slice some sort sortBy sortByDesc sortKeys sortKeysDesc splice split sum take tap times toArray toJson transform union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict whereNotNull whereNull wrap zip
方法列表
all()
这all
方法简单地返回由集合表示的底层数组:
$collection = new Collection([1, 2, 3]);
$collection->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
chunk()
这chunk
方法将集合分成多个给定大小的较小集合:
$collection = new Collection([1, 2, 3, 4, 5, 6, 7]);
$chunks = $collection->chunk(4);
$chunks->toArray();
// [[1, 2, 3, 4], [5, 6, 7]]
这种方法特别有用内容管理系统页面 使用网格系统时,例如Bootstrap.假设您有一组要在网格中显示的模型:
{% for chunk in products.chunk(3) %}
<div class="row">
{% for product in chunk %}
<div class="col-xs-4">{{ product.name }}</div>
{% endfor %}
</div>
{% endfor %}
collapse()
这collapse
方法将数组集合折叠成平面集合:
$collection = new Collection([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
$collapsed = $collection->collapse();
$collapsed->all();
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
combine()
这combine
方法将集合的值作为键与另一个数组或集合的值组合:
$collection = collect(['name', 'age']);
$combined = $collection->combine(['George', 29]);
$combined->all();
// ['name' => 'George', 'age' => 29]
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();
get_class($collection);
// 'Illuminate\Support\Collection'
$collection->all();
// [1, 2, 3]
Tip: 这
collect
当你有一个实例时,方法特别有用Enumerable
并且需要一个非惰性集合实例。自从collect()
是的一部分Enumerable
合同,你可以安全地使用它来获得Collection
实例。
concat()
这concat
方法附加给定的array
或集合值到集合的末尾:
$collection = collect(['John Doe']);
$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);
$concatenated->all();
// ['John Doe', 'Jane Doe', 'Johnny Doe']
contains()
这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
执行自己的真值测试的方法:
$collection = collect([1, 2, 3, 4, 5]);
$collection->contains(function ($value, $key) {
return $value > 5;
});
// false
这contains
方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于具有相同值的整数。使用containsStrict
使用“严格”比较进行过滤的方法。
containsStrict()
此方法具有与contains
方法;但是,所有值都使用“严格”比较进行比较。
count()
这count
方法返回集合中的项目总数:
$collection = new Collection([1, 2, 3, 4]);
$collection->count();
// 4
countBy()
这countBy
方法计算集合中值的出现次数。默认情况下,该方法计算每个元素的出现次数:
$collection = collect([1, 2, 2, 2, 3]);
$counted = $collection->countBy();
$counted->all();
// [1 => 1, 2 => 3, 3 => 1]
但是,您将回调传递给countBy
按自定义值计算所有项目的方法:
$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']);
$counted = $collection->countBy(function ($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 = new Collection([1, 2, 3, 4, 5]);
$diff = $collection->diff([2, 4, 6, 8]);
$diff->all();
// [1, 3, 5]
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]
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]
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([
['email' => 'abigail@example.com', 'position' => 'Developer'],
['email' => 'james@example.com', 'position' => 'Designer'],
['email' => 'victoria@example.com', 'position' => 'Developer'],
])
$employees->duplicates('position');
// [2 => 'Developer']
duplicatesStrict()
此方法具有与duplicates
方法;但是,所有值都使用“严格”比较进行比较。
each()
这each
方法迭代集合中的项目并将每个项目传递给回调:
$collection->each(function ($item, $key) {
//
});
如果您想停止遍历项目,您可以返回false
从你的回调:
$collection->each(function ($item, $key) {
if (/* some condition */) {
return false;
}
});
every()
这every
方法创建一个由每个第 n 个元素组成的新集合:
$collection = new Collection(['a', 'b', 'c', 'd', 'e', 'f']);
$collection->every(4);
// ['a', 'e']
您可以选择将偏移量作为第二个参数传递:
$collection->every(4, 1);
// ['b', 'f']
filter()
这filter
方法通过给定的回调过滤集合,只保留那些通过给定真值测试的项目:
$collection = new Collection([1, 2, 3, 4]);
$filtered = $collection->filter(function ($item) {
return $item > 2;
});
$filtered->all();
// [3, 4]
对于的倒数filter
, 看到reject 方法。
first()
这first
方法返回集合中通过给定真值测试的第一个元素:
new Collection([1, 2, 3, 4])->first(function ($value, $key) {
return $value > 2;
});
// 3
您也可以致电first
不带参数的方法获取集合中的第一个元素。如果集合为空,null
返回:
new Collection([1, 2, 3, 4])->first();
// 1
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
方法将返回给定项键值为“truthy”的第一个项:
$collection->firstWhere('age');
// ['name' => 'Linda', 'age' => 14]
flatMap()
这flatMap
方法遍历集合并将每个值传递给给定的回调。回调可以自由修改item并返回,这样就形成了一个新的修改item集合。然后,数组被一个级别展平:
$collection = collect([
['name' => 'Sally'],
['school' => 'Arkansas'],
['age' => 28]
]);
$flattened = $collection->flatMap(function ($values) {
return array_map('strtoupper', $values);
});
$flattened->all();
// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];
flatten()
这flatten
方法将多维集合展平为一个维度:
$collection = new Collection(['name' => 'peter', 'languages' => ['php', 'javascript']]);
$flattened = $collection->flatten();
$flattened->all();
// ['peter', 'php', 'javascript'];
flip()
这flip
方法将集合的键与其相应的值交换:
$collection = new Collection(['name' => 'peter', 'platform' => 'winter']);
$flipped = $collection->flip();
$flipped->all();
// ['peter' => 'name', 'winter' => 'platform']
forget()
这forget
方法通过其键从集合中删除一个项目:
$collection = new Collection(['name' => 'peter', 'platform' => 'winter']);
$collection->forget('name');
$collection->all();
// ['platform' => 'winter']
NOTE: 与大多数其他收集方法不同,
forget
不返回新修改的集合;它修改调用它的集合。
forPage()
这forPage
方法返回一个新集合,其中包含将出现在给定页码上的项目:
$collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8, 9])->forPage(2, 3);
$collection->all();
// [4, 5, 6]
该方法分别需要页码和每页显示的项目数。
get()
这get
方法返回给定键处的项目。如果密钥不存在,null
返回:
$collection = new Collection(['name' => 'peter', 'platform' => 'winter']);
$value = $collection->get('name');
// peter
您可以选择将默认值作为第二个参数传递:
$collection = new Collection(['name' => 'peter', 'platform' => 'winter']);
$value = $collection->get('foo', 'default-value');
// default-value
您甚至可以将回调作为默认值传递。如果指定的键不存在,将返回回调结果:
$collection->get('email', function () {
return 'default-value';
});
// default-value
groupBy()
这groupBy
方法按给定键对集合的项目进行分组:
$collection = new Collection([
['account_id' => 'account-x10', 'product' => 'Bookcase'],
['account_id' => 'account-x10', 'product' => 'Chair'],
['account_id' => 'account-x11', 'product' => 'Desk'],
]);
$grouped = $collection->groupBy('account_id');
$grouped->toArray();
/*
[
'account-x10' => [
['account_id' => 'account-x10', 'product' => 'Bookcase'],
['account_id' => 'account-x10', 'product' => 'Chair'],
],
'account-x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/
除了传递一个字符串key
,您也可以传递一个回调。回调应该返回您希望通过以下方式对组进行键控的值:
$grouped = $collection->groupBy(function ($item, $key) {
return substr($item['account_id'], -3);
});
$grouped->toArray();
/*
[
'x10' => [
['account_id' => 'account-x10', 'product' => 'Bookcase'],
['account_id' => 'account-x10', 'product' => 'Chair'],
],
'x11' => [
['account_id' => 'account-x11', 'product' => 'Desk'],
],
]
*/
has()
这has
方法确定集合中是否存在给定键:
$collection = new Collection(['account_id' => 1, 'product' => 'Desk']);
$collection->has('email');
// false
implode()
这implode
方法将项目加入集合中。它的参数取决于集合中项目的类型。
如果集合包含数组或对象,您应该传递您希望加入的属性的键,以及您希望放置在值之间的“胶水”字符串:
$collection = new Collection([
['account_id' => 1, 'product' => 'Chair'],
['account_id' => 2, 'product' => 'Desk'],
]);
$collection->implode('product', ', ');
// Chair, Desk
如果集合包含简单的字符串或数值,只需将“胶水”作为唯一参数传递给该方法:
new Collection([1, 2, 3, 4, 5])->implode('-');
// '1-2-3-4-5'
intersect()
这intersect
方法删除给定中不存在的任何值array
或收藏:
$collection = new Collection(['Desk', 'Sofa', 'Chair']);
$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);
$intersect->all();
// [0 => 'Desk', 2 => 'Chair']
如您所见,生成的集合将保留原始集合的键。
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
返回:
new Collection([])->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()
通过给定的键对集合进行键控:
$collection = new Collection([
['product_id' => 'prod-100', 'name' => 'chair'],
['product_id' => 'prod-200', 'name' => 'desk'],
]);
$keyed = $collection->keyBy('product_id');
$keyed->all();
/*
[
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Chair'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Desk'],
]
*/
如果多个项目具有相同的键,则只有最后一个项目会出现在新集合中。
您也可以传递自己的回调,它应该通过以下方式返回值以对集合进行键控:
$keyed = $collection->keyBy(function ($item) {
return strtoupper($item['product_id']);
});
$keyed->all();
/*
[
'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Chair'],
'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Desk'],
]
*/
keys()
这keys
方法返回集合的所有键:
$collection = new Collection([
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Chair'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Desk'],
]);
$keys = $collection->keys();
$keys->all();
// ['prod-100', 'prod-200']
last()
这last
方法返回集合中通过给定真值测试的最后一个元素:
new Collection([1, 2, 3, 4])->last(function ($key, $value) {
return $value < 3;
});
// 2
您也可以致电last
不带参数的方法获取集合中的最后一个元素。如果集合为空则null
被退回。
new Collection([1, 2, 3, 4])->last();
// 4
map()
这map
方法遍历集合并将每个值传递给给定的回调。回调可以自由修改item并返回,这样就形成了一个新的修改item的集合:
$collection = new Collection([1, 2, 3, 4, 5]);
$multiplied = $collection->map(function ($item, $key) {
return $item * 2;
});
$multiplied->all();
// [2, 4, 6, 8, 10]
NOTE: 与大多数其他收集方法一样,
map
返回一个新的集合实例;它不会修改调用它的集合。如果要转换原始集合,请使用transform
方法。
mapInto()
这mapInto()
方法遍历集合,通过将值传递给构造函数来创建给定类的新实例:
class Currency
{
/**
* Create a new currency instance.
*
* @param string $code
* @return void
*/
function __construct(string $code)
{
$this->code = $code;
}
}
$collection = collect(['USD', 'EUR', 'GBP']);
$currencies = $collection->mapInto(Currency::class);
$currencies->all();
// [Currency('USD'), Currency('EUR'), Currency('GBP')]
mapSpread()
这mapSpread
方法遍历集合的项目,将每个嵌套的项目值传递给给定的回调。回调可以自由修改item并返回,这样就形成了一个新的修改item的集合:
$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunks = $collection->chunk(2);
$sequence = $chunks->mapSpread(function ($even, $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 ($item, $key) {
return [$item['department'] => $item['name']];
});
$grouped->toArray();
/*
[
'Sales' => ['John Doe', 'Jane Doe'],
'Marketing' => ['Johnny Doe'],
]
*/
$grouped->get('Sales')->all();
// ['John Doe', 'Jane Doe']
mapWithKeys()
这mapWithKeys
方法遍历集合并将每个值传递给给定的回调。回调应该返回一个包含单个键/值对的关联数组:
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john@example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane@example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
return [$item['email'] => $item['name']];
});
$keyed->all();
/*
[
'john@example.com' => 'John',
'jane@example.com' => 'Jane',
]
*/
max()
这max
方法返回给定键的最大值:
$max = collect([['foo' => 10], ['foo' => 20]])->max('foo');
// 20
$max = collect([1, 2, 3, 4, 5])->max();
// 5
median()
这median
方法返回中值 给定键的:
$median = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->median('foo');
// 15
$median = collect([1, 1, 2, 4])->median();
// 1.5
merge()
这merge
方法将给定的数组或集合与原始集合合并。如果给定项中的字符串键与原始集合中的字符串键匹配,则给定项的值将覆盖原始集合中的值:
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->merge(['price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => 1, 'price' => 200, 'discount' => false]
如果给定项的键是数字,则值将附加到集合的末尾:
$collection = collect(['Desk', 'Chair']);
$merged = $collection->merge(['Bookcase', 'Door']);
$merged->all();
// ['Desk', 'Chair', 'Bookcase', 'Door']
mergeRecursive()
这mergeRecursive
方法将给定的数组或集合递归地与原始集合合并。如果给定项中的字符串键与原始集合中的字符串键匹配,则这些键的值将合并到一个数组中,这是递归完成的:
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->mergeRecursive(['product_id' => 2, 'price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
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]
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 方法。
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
方法可以与list
PHP 函数将通过给定真值测试的元素与未通过给定真值测试的元素分开:
$collection = collect([1, 2, 3, 4, 5, 6]);
list($underThree, $equalOrAboveThree) = $collection->partition(function ($i) {
return $i < 3;
});
$underThree->all();
// [1, 2]
$equalOrAboveThree->all();
// [3, 4, 5, 6]
pipe()
这pipe
方法将集合传递给给定的回调并返回结果:
$collection = collect([1, 2, 3]);
$piped = $collection->pipe(function ($collection) {
return $collection->sum();
});
// 6
pluck()
这pluck
方法检索给定键的所有集合值:
$collection = new Collection([
['product_id' => 'prod-100', 'name' => 'Chair'],
['product_id' => 'prod-200', 'name' => 'Desk'],
]);
$plucked = $collection->pluck('name');
$plucked->all();
// ['Chair', 'Desk']
您还可以指定您希望结果集合的键控方式:
$plucked = $collection->pluck('name', 'product_id');
$plucked->all();
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
pop()
这pop
方法从集合中删除并返回最后一项:
$collection = new Collection([1, 2, 3, 4, 5]);
$collection->pop();
// 5
$collection->all();
// [1, 2, 3, 4]
prepend()
这prepend
方法将一个项目添加到集合的开头:
$collection = new Collection([1, 2, 3, 4, 5]);
$collection->prepend(0);
$collection->all();
// [0, 1, 2, 3, 4, 5]
pull()
这pull
方法通过其键从集合中删除并返回一个项目:
$collection = new Collection(['product_id' => 'prod-100', 'name' => 'Desk']);
$collection->pull('name');
// 'Desk'
$collection->all();
// ['product_id' => 'prod-100']
push()
这push
方法将一个项目附加到集合的末尾:
$collection = new Collection([1, 2, 3, 4]);
$collection->push(5);
$collection->all();
// [1, 2, 3, 4, 5]
put()
这put
方法在集合中设置给定的键和值:
$collection = new Collection(['product_id' => 1, 'name' => 'Desk']);
$collection->put('price', 100);
$collection->all();
// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
random()
这random
方法从集合中返回一个随机项:
$collection = new Collection([1, 2, 3, 4, 5]);
$collection->random();
// 4 - (retrieved randomly)
您可以选择将整数传递给random
.如果该整数大于1
,返回项目集合:
$random = $collection->random(3);
$random->all();
// [2, 4, 5] - (retrieved randomly)
reduce()
这reduce
方法将集合缩减为单个值,将每次迭代的结果传递给后续迭代:
$collection = new Collection([1, 2, 3]);
$total = $collection->reduce(function ($carry, $item) {
return $carry + $item;
});
// 6
的价值$carry
第一次迭代是null
;但是,您可以通过将第二个参数传递给reduce
:
$collection->reduce(function ($carry, $item) {
return $carry + $item;
}, 4);
// 10
reject()
这reject
方法使用给定的回调过滤集合。回调应该返回true
对于它希望从生成的集合中删除的任何项目:
$collection = new Collection([1, 2, 3, 4]);
$filtered = $collection->reject(function ($item) {
return $item > 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 = new Collection([1, 2, 3, 4, 5]);
$reversed = $collection->reverse();
$reversed->all();
// [5, 4, 3, 2, 1]
search()
这search
方法在集合中搜索给定值,如果找到则返回其键。如果找不到该项目,false
被退回。
$collection = new Collection([2, 4, 6, 8]);
$collection->search(4);
// 1
搜索是使用“松散”比较完成的。要使用严格比较,通过true
作为方法的第二个参数:
$collection->search('4', true);
// false
或者,您可以传入自己的回调以搜索通过真值测试的第一个项目:
$collection->search(function ($item, $key) {
return $item > 5;
});
// 2
shift()
这shift
方法从集合中删除并返回第一项:
$collection = new Collection([1, 2, 3, 4, 5]);
$collection->shift();
// 1
$collection->all();
// [2, 3, 4, 5]
shuffle()
这shuffle
方法随机洗牌集合中的项目:
$collection = new Collection([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]
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
重新索引它们的方法。
some()
的别名contains
方法。
sort()
这sort
方法对集合进行排序:
$collection = new Collection([5, 3, 1, 2, 4]);
$sorted = $collection->sort();
$sorted->values()->all();
// [1, 2, 3, 4, 5]
排序后的集合保留了原始数组键。在这个例子中,我们使用了values
将键重置为连续编号索引的方法。
要对嵌套数组或对象的集合进行排序,请参阅sortBy
和sortByDesc
方法。
如果您的排序需求更高级,您可以将回调传递给sort
用你自己的算法。请参阅 PHP 文档usort
,这是集合的sort
引擎盖下的方法调用。
sortBy()
这sortBy
方法按给定键对集合进行排序:
$collection = new Collection([
['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],
]
*/
排序后的集合保留了原始数组键。在这个例子中,我们使用了values
将键重置为连续编号索引的方法。
您还可以通过自己的回调来确定如何对集合值进行排序:
$collection = new Collection([
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$sorted = $collection->sortBy(function ($product, $key) {
return count($product['colors']);
});
$sorted->values()->all();
/*
[
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]
*/
sortByDesc()
此方法具有与sortBy
方法,但会以相反的顺序对集合进行排序。
sortKeys()
这sortKeys
方法通过底层关联数组的键对集合进行排序:
$collection = collect([
'id' => 22345,
'first' => 'John',
'last' => 'Doe',
]);
$sorted = $collection->sortKeys();
$sorted->all();
/*
[
'first' => 'John',
'id' => 22345,
'last' => 'Doe',
]
*/
sortKeysDesc()
此方法具有与sortKeys
方法,但会以相反的顺序对集合进行排序。
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]
splice()
这splice
方法删除并返回从指定索引开始的项目切片:
$collection = new Collection([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2);
$chunk->all();
// [3, 4, 5]
$collection->all();
// [1, 2]
您可以传递第二个参数来限制结果块的大小:
$collection = new Collection([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2, 1);
$chunk->all();
// [3]
$collection->all();
// [1, 2, 4, 5]
此外,您可以传递包含新项目的第三个参数来替换从集合中删除的项目:
$collection = new Collection([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->toArray();
// [[1, 2], [3, 4], [5]]
sum()
这sum
方法返回集合中所有项目的总和:
new Collection([1, 2, 3, 4, 5])->sum();
// 15
如果集合包含嵌套数组或对象,则应传递一个键以用于确定要对哪些值求和:
$collection = new Collection([
['name' => 'JavaScript: The Good Parts', 'pages' => 176],
['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);
$collection->sum('pages');
// 1272
此外,您可以传递自己的回调来确定要对集合的哪些值求和:
$collection = new Collection([
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$collection->sum(function ($product) {
return count($product['colors']);
});
// 6
take()
这take
方法返回具有指定数量项目的新集合:
$collection = new Collection([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(3);
$chunk->all();
// [0, 1, 2]
您还可以传递一个负整数以从集合末尾获取指定数量的项目:
$collection = new Collection([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(-2);
$chunk->all();
// [4, 5]
tap()
这tap
方法将集合传递给给定的回调,允许您在特定点“点击”集合并在不影响集合本身的情况下对项目执行某些操作:
collect([2, 4, 3, 1, 5])
->sort()
->tap(function ($collection) {
Log::debug('Values after sorting', $collection->values()->toArray());
})
->shift();
// 1
times()
静态的times
方法通过调用回调给定次数来创建一个新集合:
$collection = Collection::times(10, function ($number) {
return $number * 9;
});
$collection->all();
// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
当与工厂结合创建 Eloquent 模型时,此方法很有用:
$categories = Collection::times(3, function ($number) {
return factory(Category::class)->create(['name' => "Category No. $number"]);
});
$categories->all();
/*
[
['id' => 1, 'name' => 'Category No. 1'],
['id' => 2, 'name' => 'Category No. 2'],
['id' => 3, 'name' => 'Category No. 3'],
]
*/
toArray()
这toArray
方法将集合转换为纯 PHParray
.如果集合的值是数据库模型,模型也将被转换为数组:
$collection = new Collection(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
/*
[
['name' => 'Desk', 'price' => 200],
]
*/
NOTE:
toArray
还将其所有嵌套对象转换为数组。如果您想按原样获取基础数组,请使用all
方法代替。
toJson()
这toJson
方法将集合转换为 JSON:
$collection = new Collection(['name' => 'Desk', 'price' => 200]);
$collection->toJson();
// '{"name":"Desk","price":200}'
transform()
这transform
方法遍历集合并调用集合中每个项目的给定回调。集合中的项目将被回调返回的值替换:
$collection = new Collection([1, 2, 3, 4, 5]);
$collection->transform(function ($item, $key) {
return $item * 2;
});
$collection->all();
// [2, 4, 6, 8, 10]
NOTE: 与大多数其他收集方法不同,
transform
修改集合本身。如果您希望创建一个新集合,请使用map
方法。
union()
这union
方法将给定的数组添加到集合中。如果给定数组包含原始集合中已有的键,则将首选原始集合的值:
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['b']]);
$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 = $collection->unique(function ($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
使用“严格”比较进行过滤的方法。
uniqueStrict()
此方法具有与unique
方法;但是,所有值都使用“严格”比较进行比较。
unless()
这unless
方法将执行给定的回调,除非给方法的第一个参数的计算结果为true
:
$collection = collect([1, 2, 3]);
$collection->unless(true, function ($collection) {
return $collection->push(4);
});
$collection->unless(false, function ($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'
values()
这values
方法返回一个新集合,其中的键重置为连续的整数:
$collection = new Collection([
10 => ['product' => 'Desk', 'price' => 200],
11 => ['product' => 'Desk', 'price' => 200]
]);
$values = $collection->values();
$values->all();
/*
[
0 => ['product' => 'Desk', 'price' => 200],
1 => ['product' => 'Desk', 'price' => 200],
]
*/
when()
这when
当提供给方法的第一个参数的计算结果为时,方法将执行给定的回调true
:
$collection = collect([1, 2, 3]);
$collection->when(true, function ($collection) {
return $collection->push(4);
});
$collection->when(false, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 4]
对于的倒数when
, 看到unless
方法。
whenEmpty()
这whenEmpty
方法将在集合为空时执行给定的回调:
$collection = collect(['michael', 'tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['michael', 'tom']
$collection = collect();
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['adam']
$collection = collect(['michael', 'tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
}, function ($collection) {
return $collection->push('taylor');
});
$collection->all();
// ['michael', 'tom', 'taylor']
对于的倒数whenEmpty
, 看到whenNotEmpty
方法。
whenNotEmpty()
这whenNotEmpty
当集合不为空时,方法将执行给定的回调:
$collection = collect(['michael', 'tom']);
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['michael', 'tom', 'adam']
$collection = collect();
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// []
$collection = collect();
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
}, function ($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\User;
use App\Post;
$collection = collect([
new User,
new User,
new Post,
]);
$filtered = $collection->whereInstanceOf(User::class);
$filtered->all();
// [App\User, App\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
方法过滤给定键不为空的项目:
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNotNull('name');
$filtered->all();
/*
[
['name' => 'Desk'],
['name' => 'Bookcase'],
]
*/
whereNull()
这whereNull
方法过滤给定键为空的项目:
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNull('name');
$filtered->all();
/*
[
['name' => null],
]
*/
wrap()
静态的wrap
方法在适用时将给定值包装在集合中:
$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
,some
,sortBy
,sortByDesc
,sum
, 和unique
.
每个高阶消息都可以作为集合实例上的动态属性进行访问。例如,让我们使用each
在集合中的每个对象上调用方法的高阶消息:
$users = User::where('votes', '>', 500)->get();
$users->each->markAsVip();
同样,我们可以使用sum
收集一组用户的“投票”总数的高阶消息:
$users = User::where('group', 'Development')->get();
return $users->sum->votes;
惰性集合
Introduction
NOTE: 在进一步了解 Winter 的懒人系列之前,请先花点时间熟悉一下PHP 生成器.
补充已经强大的Collection
类,LazyCollection
类利用 PHP 的generators 允许您处理非常大的数据集,同时保持低内存使用率。
例如,假设您的应用程序需要处理一个数 GB 的日志文件,同时利用 Winter 的收集方法来解析日志。惰性集合可用于在给定时间仅将文件的一小部分保留在内存中,而不是一次将整个文件读入内存:
use App\LogEntry;
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
})->chunk(4)->map(function ($lines) {
return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
// Process the log entry...
});
或者,假设您需要迭代 10,000 个 Eloquent 模型。使用传统的 Winter 集合时,所有 10,000 个 Eloquent 模型必须同时加载到内存中:
$users = App\User::all()->filter(function ($user) {
return $user->id > 500;
});
但是,查询生成器的cursor
方法返回一个LazyCollection
实例。这允许您仍然只对数据库运行一个查询,而且一次只将一个 Eloquent 模型加载到内存中。在这个例子中,filter
在我们实际单独迭代每个用户之前不会执行回调,从而大幅减少内存使用:
$users = App\User::cursor()->filter(function ($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 collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys dump duplicates duplicatesStrict each eachSpread every except filter first firstWhere flatMap flatten flip forPage get groupBy has implode intersect 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 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
NOTE: 改变集合的方法(例如
shift
,pop
,prepend
等)是not 可在LazyCollection
班级。
惰性收集方法
除了定义在Enumerable
合同,LazyCollection
类包含以下方法:
tapEach()
虽然each
方法立即为集合中的每个项目调用给定的回调,tapEach
方法只调用给定的回调,因为项目被一个接一个地拉出列表:
$lazyCollection = LazyCollection::times(INF)->tapEach(function ($value) {
dump($value);
});
// Nothing has been dumped so far...
$array = $lazyCollection->take(3)->all();
// 1
// 2
// 3
remember()
这remember
方法返回一个新的惰性集合,它将记住任何已经枚举过的值,并且在再次枚举集合时不会再次检索它们:
$users = User::cursor()->remember();
// No query has been executed yet...
$users->take(5)->all();
// The query has been executed and the first 5 users have been hydrated from the database...
$users->take(20)->all();
// First 5 users come from the collection's cache... The rest are hydrated from the database...