集合
集合
简介
Illuminate\Support\Collection
类为处理数据数组提供了流利、便利的封装。例如,请查看以下代码。我们将使用 collect
辅助函数从数组创建新的 collection 实例,对每个元素运行 strtoupper
函数,然后移除所有空元素:
$collection = collect(['taylor', 'abigail', null])->map(function (?string $name) {
return strtoupper($name);
})->reject(function (string $name) {
return empty($name);
});
如你所见,Collection
类允许你链式调用其方法,以流畅地映射和简化底层数组。一般来说,collections 是不可变的,这意味着每个 Collection
方法都返回全新的 Collection
实例。
创建集合
正如上面提到的,collect
辅助函数为给定数组返回新的 Illuminate\Support\Collection
实例。因此,创建一个 collection 就像这样简单:
$collection = collect([1, 2, 3]);
注意
Eloquent 查询的结果始终返回为Collection
实例。
扩展集合
Collections 是「可宏编程的」,这允许你在运行时向 Collection
类添加附加方法。Illuminate\Support\Collection
类的 macro
方法接受一个闭包,该闭包在调用宏时将被执行。宏闭包可以通过 $this
访问 collection 的其他方法,就好像它是 collection 类的一个真实方法。例如,以下代码向 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
方法中声明 collection 宏。
宏参数
如果需要,你可以定义接受额外参数的宏:
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
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
方法列表
<code>after()</code> {.collection-method .first-collection-method}
after
方法返回给定项之后的项如果找不到给定的项或该项是最后一个项,则返回 null
:
$collection = collect([1, 2, 3, 4, 5]);
$collection->after(3);
// 4
$collection->after(5);
// null
此方法使用「loose」比较来搜索给定项,这意味着包含整数值的字符串将被视为等于相同值的整数。要使用strict
比较,可以为该方法提供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
<code>all()</code> {.collection-method}
all
方法返回由 collection 表示的底层数组:
collect([1, 2, 3])->all();
// [1, 2, 3]
<code>average()</code> {.collection-method}
avg
方法的别名。
<code>avg()</code> {.collection-method}
avg
方法返回给定键的 平均值:
$average = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->avg('foo');
// 20
$average = collect([1, 1, 2, 4])->avg();
// 2
<code>before()</code> {.collection-method}
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
<code>chunk()</code>
chunk
方法将集合分成多个给定大小的较小集合:
$collection = collect([1, 2, 3, 4, 5, 6, 7]);
$chunks = $collection->chunk(4);
$chunks->all();
// [[1, 2, 3, 4], [5, 6, 7]]
当使用诸如 Bootstrap 之类的网格系统时,此方法在 views 中特别有用。例如,假设你有一组 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
<code>chunkWhile()</code>
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']]
<code>collapse()</code>
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]
<code>collect()</code>
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
实例。
<code>combine()</code>
combine
方法将集合的值作为键与另一个数组或集合的值组合:
$collection = collect(['name', 'age']);
$combined = $collection->combine(['George', 29]);
$combined->all();
// ['name' => 'George', 'age' => 29]
<code>concat()</code>
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 方法。
<code>contains()</code>
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 方法。
<code>containsOneItem()</code> {集合方法}
containsOneItem
方法确定集合是否包含单个项目:
collect([])->containsOneItem();
// false
collect(['1'])->containsOneItem();
// true
collect(['1', '2'])->containsOneItem();
// false
<code>containsStrict()</code> {集合方法}
该方法的签名与 contains
方法相同,但所有值都使用「严格」比较法进行比较。
注意
当使用Eloquent 集合
时,此方法的行为会有所改变。
<code>count()</code> {集合方法}
count
方法返回集合中项目的总数:
$collection = collect([1, 2, 3, 4]);
$collection->count();
// 4
<code>countBy()</code> {集合方法}
countBy
方法计算值在集合中的出现次数。默认情况下,该方法会统计每个元素的出现次数,也允许统计集合中某些 「类型」的元素:
$collection = collect([1, 2, 2, 2, 3]);
$counted = $collection->countBy();
$counted->all();
// [1 => 1, 2 => 3, 3 => 1]
你可以向 countBy
方法传递一个闭包,以便按自定义值对所有项目进行计数
$collection = collect(['[email protected]', '[email protected]', '[email protected]']);
$counted = $collection->countBy(function (string $email) {
return substr(strrchr($email, "@"), 1);
});
$counted->all();
// ['gmail.com' => 2, 'yahoo.com' => 1]
<code>crossJoin()</code> {集合方法}
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'],
]
*/
<code>dd()</code> {.collection-method}
dd
方法打印集合的项目并结束脚本执行:
$collection = collect(['John Doe', 'Jane Doe']);
$collection->dd();
/*
Collection {
#items: array:2 [
0 => "John Doe"
1 => "Jane Doe"
]
}
*/
如果你不想在打印集合之后停止执行脚本,请改用 dump
方法。
<code>diff()</code> {.collection-method}
diff
方法基于值将集合与另一个集合或普通 PHP array
进行比较。此方法将返回原始集合中未出现在给定集合中的值:
$collection = collect([1, 2, 3, 4, 5]);
$diff = $collection->diff([2, 4, 6, 8]);
$diff->all();
// [1, 3, 5]
注意
使用 Eloquent 集合时,此方法的行为会发生变化。
<code>diffAssoc()</code> {.collection-method}
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]
<code>diffAssocUsing()</code> {.collection-method}
与 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 函数。
<code>diffKeys()</code> {.collection-method}
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]
<code>doesntContain()</code> {.collection-method}
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
方法在检查项目值时使用「松散」比较,意味着一个具有整数值的字符串将被认为等同于同一值的整数。
<code>dot()</code> {.collection-method}
dot
方法将多维集合展平成单一层级集合,使用「.」符号表示深度:
$collection = collect(['products' => ['desk' => ['price' => 100]]]);
$flattened = $collection->dot();
$flattened->all();
// ['products.desk.price' => 100]
<code>dump()</code> {.collection-method}
dump
方法转储集合的项目:
$collection = collect(['John Doe', 'Jane Doe']);
$collection->dump();
/*
Collection {
#items: array:2 [
0 => "John Doe"
1 => "Jane Doe"
]
}
*/
如果要在转储集合后停止执行脚本,请改用 dd
方法。
<code>duplicates()</code> {.collection-method}
duplicates
方法从集合中检索并返回重复值:
$collection = collect(['a', 'b', 'a', 'c', 'b']);
$collection->duplicates();
// [2 => 'a', 4 => 'b']
如果集合包含数组或对象,你可以传递要检查重复值的属性的键:
$employees = collect([
['email' => '[email protected]', 'position' => 'Developer'],
['email' => '[email protected]', 'position' => 'Designer'],
['email' => '[email protected]', 'position' => 'Developer'],
]);
$employees->duplicates('position');
// [2 => 'Developer']
<code>duplicatesStrict()</code> {.collection-method}
此方法与 duplicates
方法具有相同的签名;但是,所有值都使用「严格」比较进行比较。
<code>each()</code> {.collection-method}
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;
}
});
<code>eachSpread()</code> {.collection-method}
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;
});
<code>ensure()</code> {.collection-method}
ensure
方法可用于验证集合的所有元素是否为给定类型或类型列表。否则,将抛出 UnexpectedValueException
:
return $collection->ensure(User::class);
return $collection->ensure([User::class, Customer::class]);
也可以指定 string
、int
、float
、bool
和 array
等原始类型:
return $collection->ensure('int');
注意
ensure
方法不能保证不同类型的元素以后不会被添加到集合中。
<code>every()</code> {.collection-method}
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
<code>except()</code> {.collection-method}
except
方法返回集合中的所有项目,除了具有指定键的项目:
$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);
$filtered = $collection->except(['price', 'discount']);
$filtered->all();
// ['product_id' => 1]
与 except
相反的方法,请参见 only 方法。
注意
使用 Eloquent 集合时,此方法的行为会发生变化。
<code>filter()</code> {.collection-method}
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 方法。
<code>first()</code> {.collection-method}
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
<code>firstOrFail()</code> {.collection-method}
firstOrFail
方法与 first
方法相同;但是,如果没有找到结果,将抛出 Illuminate/Support/ItemNotFoundException
异常。
collect([1, 2, 3, 4])->firstOrFail(function (int $value, int $key) {
return $value > 5;
});
// 抛出 ItemNotFoundException....
你也可以不带参数调用 firstOrFail
方法,以获得集合中的第一个元素。如果集合是空的,将抛出一个 Illuminate\Support\ItemNotFoundException
异常。
collect([])->firstOrFail();
// 抛出 ItemNotFoundException...
<code>firstWhere()</code> {.collection-method}
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]
<code>flatMap()</code> {.collection-method}
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'];
<code>flatten()</code> {.collection-method}
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']
。提供深度允许你指定嵌套数组将被展平的级别数。
<code>flip()</code> {.collection-method}
flip
方法将集合的键与其对应的值交换:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$flipped = $collection->flip();
$flipped->all();
// ['taylor' => 'name', 'laravel' => 'framework']
<code>forget()</code> {.collection-method}
forget
方法将通过指定的键来移除集合中对应的元素:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$collection->forget('name');
$collection->all();
// ['framework' => 'laravel']
注意
与大多数集合的方法不同的是,forget
不会返回修改后的新集合;它会直接修改原集合。
<code>forPage()</code> {.collection-method}
forPage
方法返回一个含有指定页码数集合项的新集合。这个方法接受页码数作为其第一个参数,每页显示的项数作为其第二个参数:
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunk = $collection->forPage(2, 3);
$chunk->all();
// [4, 5, 6]
<code>get()</code> {.collection-method}
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 () {
return '[email protected]';
});
// [email protected]
<code>groupBy()</code> {.collection-method}
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']],
],
],
];
*/
<code>has()</code> {.collection-method}
has
方法确定集合中是否存在给定键:
$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);
$collection->has('product');
// true
$collection->has(['product', 'amount']);
// true
$collection->has(['amount', 'price']);
// false
<code>hasAny()</code> {.collection-method}
hasAny
方法确定在集合中是否存在任何给定的键。
$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);
$collection->hasAny(['product', 'price']);
// true
$collection->hasAny(['name', 'price']);
// false
<code>implode()</code> {.collection-method}
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
<code>intersect()</code> {.collection-method}
intersect
方法从原始集合中删除任何不存在于给定 array
或集合中的值。生成的集合将保留原始集合的键:
$collection = collect(['Desk', 'Sofa', 'Chair']);
$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);
$intersect->all();
// [0 => 'Desk', 2 => 'Chair']
注意
使用 Eloquent 集合 时会修改此方法的行为。
<code>intersectAssoc()</code> {.collection-method}
intersectAssoc
方法将原始集合与另一个集合或 array
进行比较,返回所有给定集合中存在的键 / 值对:
$collection = collect([
'color' => 'red',
'size' => 'M',
'material' => 'cotton'
]);
$intersect = $collection->intersectAssoc([
'color' => 'blue',
'size' => 'M',
'material' => 'polyester'
]);
$intersect->all();
// ['size' => 'M']
<code>intersectByKeys()</code> {.collection-method}
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]
<code>isEmpty()</code> {.collection-method}
如果集合为空,isEmpty
方法返回 true
;否则,返回 false
:
collect([])->isEmpty();
// true
<code>isNotEmpty()</code> {.collection-method}
如果集合不为空,isNotEmpty
方法返回 true
;否则,返回 false
:
collect([])->isNotEmpty();
// false
<code>join()</code> {.collection-method}
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 '); // ''
<code>keyBy()</code> {.collection-method}
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'],
]
*/
<code>keys()</code> {.collection-method}
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']
<code>last()</code> {.collection-method}
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
<code>lazy()</code> {.collection-method}
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
,我们避免了分配大量额外的内存。尽管原始集合仍保持着它的值在内存中,但随后的过滤不会。因此,在过滤集合结果时几乎不会分配额外的内存。
<code>macro()</code> {.collection-method}
静态 macro()
方法允许你在运行时向「集合」类添加方法。有关详细信息,请参阅有关 扩展集合 的文档。
<code>make()</code> {.collection-method}
静态 make
方法可以创建一个新的集合实例。请参照 创建集合 部分。
<code>map()</code> {.collection-method}
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
方法。
<code>mapInto()</code> {.collection-method}
mapInto()
方法可以迭代集合,通过将值传递给构造函数来创建给定类的新实例:
class Currency
{
/**
* 创建一个新的 currency 实例
*/
function __construct(
public string $code
) {}
}
$collection = collect(['USD', 'EUR', 'GBP']);
$currencies = $collection->mapInto(Currency::class);
$currencies->all();
// [Currency('USD'), Currency('EUR'), Currency('GBP')]
<code>mapSpread()</code> {.collection-method}
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]
<code>mapToGroups()</code> {.collection-method}
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']
<code>mapWithKeys()</code> {.collection-method}
mapWithKeys
方法遍历集合并将每个值传递给给定的回调。回调应返回包含单个键 / 值对的关联数组:
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => '[email protected]',
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => '[email protected]',
]
]);
$keyed = $collection->mapWithKeys(function (array $item, int $key) {
return [$item['email'] => $item['name']];
});
$keyed->all();
/*
[
'[email protected]' => 'John',
'[email protected]' => 'Jane',
]
*/
<code>max()</code> {.collection-method}
max
方法返回给定键的最大值:
$max = collect([
['foo' => 10],
['foo' => 20]
])->max('foo');
// 20
$max = collect([1, 2, 3, 4, 5])->max();
// 5
<code>median()</code> {.collection-method}
median
方法返回给定键的 中值:
$median = collect([
['foo' => 10],
['foo' => 10],
['foo' => 20],
['foo' => 40]
])->median('foo');
// 15
$median = collect([1, 1, 2, 4])->median();
// 1.5
<code>merge()</code> {.collection-method}
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']
<code>mergeRecursive()</code> {.collection-method}
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]
<code>min()</code> {.collection-method}
min
方法返回给定键的最小值:
$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');
// 10
$min = collect([1, 2, 3, 4, 5])->min();
// 1
<code>mode()</code> {.collection-method}
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]
<code>nth()</code> {.collection-method}
nth
方法创建一个由每隔第 n 个元素组成的新集合:
$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);
$collection->nth(4);
// ['a', 'e']
你可以选择将起始偏移量作为第二个参数传递:
$collection->nth(4, 1);
// ['b', 'f']
<code>only()</code> {.collection-method}
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 集合 时,这个方法的行为有所不同。
<code>pad()</code> {.collection-method}
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']
<code>partition()</code> {.collection-method}
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]
<code>percentage()</code> {.collection-method}
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
<code>pipe()</code> {.collection-method}
pipe
方法将集合传递给给定闭包,并返回执行闭包的结果:
$collection = collect([1, 2, 3]);
$piped = $collection->pipe(function (Collection $collection) {
return $collection->sum();
});
// 6
<code>pipeInto()</code> {.collection-method}
pipeInto
方法创建指定类的新实例,并将集合传入构造函数:
class ResourceCollection
{
/**
* 创建一个新 ResourceCollection 实例。
*/
public function __construct(
public Collection $collection,
) {}
}
$collection = collect([1, 2, 3]);
$resource = $collection->pipeInto(ResourceCollection::class);
$resource->collection->all();
// [1, 2, 3]
<code>pipeThrough()</code> {.collection-method}
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
<code>pluck()</code> {.collection-method}
pluck
可以获取集合中指定键对应的所有值:
$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$plucked = $collection->pluck('name');
$plucked->all();
// ['Desk', 'Chair']
你也可以通过传入第二个参数来指定生成集合的 key(键):
$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']]
如果存在重复键,则将最后一个匹配元素插入到 plucked 集合中:
$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']
<code>pop()</code> {.collection-method}
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]
<code>prepend()</code> {.collection-method}
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]
<code>pull()</code> {.collection-method}
pull
方法通过其键移除并返回集合中的一个项目:
$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);
$collection->pull('name');
// 'Desk'
$collection->all();
// ['product_id' => 'prod-100']
<code>push()</code> {.collection-method}
push
方法将一个项目追加到集合的末尾:
$collection = collect([1, 2, 3, 4]);
$collection->push(5);
$collection->all();
// [1, 2, 3, 4, 5]
<code>put()</code> {.collection-method}
put
方法在集合中设置给定的键和值:
$collection = collect(['product_id' => 1, 'name' => 'Desk']);
$collection->put('price', 100);
$collection->all();
// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
<code>random()</code> {.collection-method}
random
方法从集合中返回一个随机项目:
$collection = collect([1, 2, 3, 4, 5]);
$collection->random();
// 4 - (随机获取)
你可以将一个整数传递给 random
,以指定要随机检索的项目数。当明确传递你希望接收的项目数时,始终返回项目集合:
$random = $collection->random(3);
$random->all();
// [2, 4, 5] - (随机获取)
如果集合实例中的项目少于请求的数量,random
方法将抛出一个 InvalidArgumentException
异常。
random
方法也接受一个闭包,该闭包将接收当前集合实例:
use Illuminate\Support\Collection;
$random = $collection->random(fn (Collection $items) => min(10, count($items)));
$random->all();
// [1, 2, 3, 4, 5] - (随机获取)
<code>range()</code> {.collection-method}
range
方法返回一个包含指定范围之间整数的集合:
$collection = collect()->range(3, 6);
$collection->all();
// [3, 4, 5, 6]
<code>reduce()</code> {.collection-method}
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
<code>reduceSpread()</code> {.collection-method}
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());
<code>reject()</code> {.collection-method}
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
方法。
<code>replace()</code> {.collection-method}
replace
方法的行为类似于 merge
;但是,除了覆盖具有字符串键的匹配项之外,replace
方法还将覆盖具有匹配数字键的集合中的项:
$collection = collect(['Taylor', 'Abigail', 'James']);
$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);
$replaced->all();
// ['Taylor', 'Victoria', 'James', 'Finn']
<code>replaceRecursive()</code> {.collection-method}
这个方法的工作原理类似于 replace
,但它将递归到数组中,并将相同的替换过程应用于内部值:
$collection = collect([
'Taylor',
'Abigail',
[
'James',
'Victoria',
'Finn'
]
]);
$replaced = $collection->replaceRecursive([
'Charlie',
2 => [1 => 'King']
]);
$replaced->all();
// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]
<code>reverse()</code> {.collection-method}
reverse
方法反转集合项的顺序,保留原始键:
$collection = collect(['a', 'b', 'c', 'd', 'e']);
$reversed = $collection->reverse();
$reversed->all();
/*
[
4 => 'e',
3 => 'd',
2 => 'c',
1 => 'b',
0 => 'a',
]
*/
<code>search()</code> {.collection-method}
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
<code>select()</code> {.collection-method}
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'],
],
*/
<code>shift()</code> {.collection-method}
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]
<code>shuffle()</code> {.collection-method}
shuffle
方法随机地打乱集合中的项:
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (随机生成)
<code>skip()</code> {.collection-method}
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]
<code>skipUntil()</code> {.collection-method}
skipUntil
方法跳过集合中的项目,直到给定的回调返回 true
,然后将集合中的剩余项目作为新的集合实例返回:
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipUntil(function (int $item) {
return $item >= 3;
});
$subset->all();
// [3, 4]
你还可以将一个简单的值传递给 skipUntil
方法以跳过所有项目,直到找到给定值:
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipUntil(3);
$subset->all();
// [3, 4]
注意
如果没有找到给定的值或者回调从未返回true
,skipUntil
方法将返回一个空集合。
<code>skipWhile()</code> {.collection-method}
skipWhile
方法在给定回调返回 true
时跳过集合中的项目,然后将集合中的剩余项目作为新集合返回:
$collection = collect([1, 2, 3, 4]);
$subset = $collection->skipWhile(function (int $item) {
return $item <= 3;
});
$subset->all();
// [4]
注意
如果回调从未返回false
,skipWhile
方法将返回一个空集合。
<code>slice()</code> {.collection-method}
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
方法来重新索引它们。
<code>sliding()</code> {.collection-method}
sliding
方法返回一个新的块集合,表示集合中项目的「滑动窗口」视图:
$collection = collect([1, 2, 3, 4, 5]);
$chunks = $collection->sliding(2);
$chunks->toArray();
// [[1, 2], [2, 3], [3, 4], [4, 5]]
这与 eachSpread
方法结合使用特别有用:
$transactions->sliding(2)->eachSpread(function (Collection $previous, Collection $current) {
$current->total = $previous->total + $current->amount;
});
你可以选择传递第二个「步长」值,该值确定每个块的第一项之间的距离:
$collection = collect([1, 2, 3, 4, 5]);
$chunks = $collection->sliding(3, step: 2);
$chunks->toArray();
// [[1, 2, 3], [3, 4, 5]]
<code>sole()</code> {.collection-method}
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
异常。
<code>some()</code> {.collection-method}
contains
方法的别名。
<code>sort()</code> {.collection-method}
sort
方法对集合进行排序。排序后的集合保留了原始数组键,因此在下面的示例中,我们将使用 values
方法将键重置为连续编号的索引:
$collection = collect([5, 3, 1, 2, 4]);
$sorted = $collection->sort();
$sorted->values()->all();
// [1, 2, 3, 4, 5]
如果你的排序需求更高级,你可以使用自己的算法将回调传递给「排序」。参考 PHP 文档 uasort
,这正是集合的 sort 方法内部调用的方法。
技巧
如果你需要对嵌套数组或对象的集合进行排序,请参阅sortBy
和sortByDesc
方法。
<code>sortBy()</code> {.collection-method}
sortBy
方法按给定键对集合进行排序。排序后的集合保留了原始数组键,因此在下面的示例中,我们将使用 values
方法将键重置为连续编号的索引:
$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
/*
[
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
['name' => 'Desk', 'price' => 200],
]
*/
sortBy
方法接受 sort flags 作为其第二个参数:
$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],
]
*/
<code>sortByDesc()</code> {.collection-method}
此方法与 sortBy
方法具有相同的签名,但将以相反的顺序对集合进行排序。
<code>sortDesc()</code> {.collection-method}
此方法将按照与 sort
方法相反的顺序对集合进行排序:
$collection = collect([5, 3, 1, 2, 4]);
$sorted = $collection->sortDesc();
$sorted->values()->all();
// [5, 4, 3, 2, 1]
与 sort
不同,你不能将闭包传递给 sortDesc
。相反,你应该使用 sort
方法并反转比较。
<code>sortKeys()</code> {.collection-method}
sortKeys
方法通过底层关联数组的键对集合进行排序:
$collection = collect([
'id' => 22345,
'first' => 'John',
'last' => 'Doe',
]);
$sorted = $collection->sortKeys();
$sorted->all();
/*
[
'first' => 'John',
'id' => 22345,
'last' => 'Doe',
]
*/
<code>sortKeysDesc()</code> {.collection-method}
此方法与 sortKeys
方法具有相同的签名,但将以相反的顺序对集合进行排序。
<code>sortKeysUsing()</code> {.collection-method}
sortKeysUsing
方法使用回调通过底层关联数组的键对集合进行排序:
$collection = collect([
'ID' => 22345,
'first' => 'John',
'last' => 'Doe',
]);
$sorted = $collection->sortKeysUsing('strnatcasecmp');
$sorted->all();
/*
[
'first' => 'John',
'ID' => 22345,
'last' => 'Doe',
]
*/
回调必须是返回小于、等于或大于零的整数的比较函数。有关更多信息,请参阅 uksort
上的 PHP 文档,sortKeysUsing
方法在内部使用了这个 PHP 函数。
<code>splice()</code> {.collection-method}
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]
<code>split()</code> {.collection-method}
split
方法将集合分成给定数量的组:
$collection = collect([1, 2, 3, 4, 5]);
$groups = $collection->split(3);
$groups->all();
// [[1, 2], [3, 4], [5]]
<code>splitIn()</code> {.collection-method}
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]]
<code>sum()</code> {.collection-method}
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
<code>take()</code> {.collection-method}
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]
<code>takeUntil()</code> {.collection-method}
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
方法将返回集合中的所有项目。
<code>takeWhile()</code> {.collection-method}
takeWhile
方法返回集合中的项目,直到给定的回调返回 false
:
$collection = collect([1, 2, 3, 4]);
$subset = $collection->takeWhile(function (int $item) {
return $item < 3;
});
$subset->all();
// [1, 2]
注意
如果回调从不返回false
,则takeWhile
方法将返回集合中的所有项目。
<code>tap()</code> {.collection-method}
tap
方法将集合传递给给定的回调,允许你在特定点「点击」到集合中并在不影响集合本身的情况下对项目执行某些操作。然后集合由 tap
方法返回:
collect([2, 4, 3, 1, 5])
->sort()
->tap(function (Collection $collection) {
Log::debug('Values after sorting', $collection->values()->all());
})
->shift();
// 1
<code>times()</code> {.collection-method}
静态 times
方法通过调用给定次数的回调函数来创建新集合:
$collection = Collection::times(10, function (int $number) {
return $number * 9;
});
$collection->all();
// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
<code>toArray()</code> {.collection-method}
该 toArray
方法将集合转换成 PHP array
。如果集合的值是 Eloquent 模型,那也会被转换成数组:
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
/*
[
['name' => 'Desk', 'price' => 200],
]
*/
注意
toArray
也会将Arrayable
的实例、所有集合的嵌套对象转换为数组。如果你想获取原数组,可以使用all
方法。
<code>toJson()</code> {.collection-method}
toJson
方法将集合转换成 JSON 字符串:
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toJson();
// '{"name":"Desk", "price":200}'
<code>transform()</code> {.collection-method}
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
方法。
<code>undot()</code> {.collection-method}
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",
],
]
*/
<code>union()</code> {.collection-method}
union
方法将给定数组添加到集合中。如果给定的数组含有与原集合一样的键,则首选原始集合的值:
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['d']]);
$union->all();
// [1 => ['a'], 2 => ['b'], 3 => ['c']]
<code>unique()</code> {.collection-method}
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 集合 时被修改。
<code>uniqueStrict()</code> {.collection-method}
这个方法与 unique
方法一样,然而,所有的值是用「严格」模式来比较的。
<code>unless()</code> {.collection-method}
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
方法。
<code>unlessEmpty()</code> {.collection-method}
whenNotEmpty
的别名方法。
<code>unlessNotEmpty()</code> {.collection-method}
whenEmpty
的别名方法。
<code>unwrap()</code> {.collection-method}
静态 unwrap
方法返回集合内部的可用元素:
Collection::unwrap(collect('John Doe'));
// ['John Doe']
Collection::unwrap(['John Doe']);
// ['John Doe']
Collection::unwrap('John Doe');
// 'John Doe'
<code>value()</code> {.collection-method}
value
方法从集合的第一个元素中检索一个给定的值。
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Speaker', 'price' => 400],
]);
$value = $collection->value('price');
// 200
<code>values()</code> {.collection-method}
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],
]
*/
<code>when()</code> {.collection-method}
当 when
方法的第一个参数传入为 true
时,将执行给定的回调函数。集合实例和给到 when
方法的第一个参数将被提供给闭包。
$collection = collect([1, 2, 3]);
$collection->when(true, function (Collection $collection, int $value) {
return $collection->push(4);
});
$collection->when(false, function (Collection $collection, int $value) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 4]
可以将第二个回调传递给该 when
方法。当给 when
方法的第一个参数计算结果为 false
时,将执行第二个回调:
$collection = collect([1, 2, 3]);
$collection->when(false, function (Collection $collection, int $value) {
return $collection->push(4);
}, function (Collection $collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 5]
与 when
相反的方法,请查看 unless
方法。
<code>whenEmpty()</code> {.collection-method}
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
方法。
<code>whenNotEmpty()</code> {.collection-method}
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
方法。
<code>where()</code> {.collection-method}
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'],
]
*/
<code>whereStrict()</code> {.collection-method}
此方法和 where
方法使用相似;但是它是「严格」模式去匹配值和类型。
<code>whereBetween()</code> {.collection-method}
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],
]
*/
<code>whereIn()</code> {.collection-method}
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
) 方法。
<code>whereInStrict()</code> {.collection-method}
此方法与 whereIn
方法有相同的签名,但所有值都会使用「严格」比较进行比较。
<code>whereInstanceOf()</code> {.collection-method}
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]
<code>whereNotBetween()</code> {.collection-method}
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],
]
*/
<code>whereNotIn()</code> {.collection-method}
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
方法。
<code>whereNotInStrict()</code> {.collection-method}
这个方法与 whereNotIn
方法类似;不同的是会使用「严格」模式比较。
<code>whereNotNull()</code> {.collection-method}
whereNotNull
方法筛选给定键不为 null
的项:
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNotNull('name');
$filtered->all();
/*
[
['name' => 'Desk'],
['name' => 'Bookcase'],
]
*/
<code>whereNull()</code> {.collection-method}
whereNull
方法筛选给定键为 null
的项:
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNull('name');
$filtered->all();
/*
[
['name' => null],
]
*/
<code>wrap()</code> {.collection-method}
静态 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']
<code>zip()</code> {.collection-method}
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
高阶消息来收集用户集合的「votes」总数:
$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) {
// 处理日志条目...
});
或者,假设你需要遍历 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
注意
在LazyCollection
类上,会变更集合自身的方法(例如shift
、pop
、prepend
等)是不可用的。
惰性集合方法
除了在 Enumerable
契约中定义的方法外, LazyCollection
类还包含以下方法:
<code>takeUntilTimeout()</code>
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());
<code>tapEach()</code>
当 each
方法为集合中每一个元素调用给定回调时, tapEach
方法仅调用给定回调,因为这些元素正在逐个从列表中拉出:
// 没有任何输出
$lazyCollection = LazyCollection::times(INF)->tapEach(function (int $value) {
dump($value);
});
// 打印出 3 条数据
$array = $lazyCollection->take(3)->all();
// 1
// 2
// 3
<code>throttle()</code>
throttle
方法将限制惰性集合,使得每个值在指定的秒数后返回。此方法在与限制传入请求速率的外部 API 交互的情况下特别有用:
use App\Models\User;
User::where('vip', true)
->cursor()
->throttle(seconds: 1)
->each(function (User $user) {
// 调用外部 API
});
<code>remember()</code>
remember
方法返回一个新的惰性集合,这个集合已经记住(缓存)已枚举的所有值,当再次枚举该集合时不会获取它们:
// 没执行任何查询
$users = User::cursor()->remember();
// 执行了查询操作
// 并且前 5 个用户数据已经在数据库中查询完成
$users->take(5)->all();
// 前 5 个用户数据从缓存中获取
// 剩余的(15 个)用户数据从数据库中查询
$users->take(20)->all();
原文地址:cndocs/11.x/co...
译文地址:cndocs/11.x/co...