集合

未匹配的标注
本文档最新版为 10.x,旧版本可能放弃维护,推荐阅读最新版!

集合

简介

Illuminate\Support\Collection 类提供了一个更具可读性和更便于处理数组数据的封装。具体请查看下方示例代码。 我们使用 collect 辅助函数从数组中创建一个新的集合实例,对其中每一个元素执行 strtoupper 函数之后再删除所有的空元素:

$collection = collect(['taylor', 'abigail', null])->map(function ($name) {
    return strtoupper($name);
})->reject(function ($name) {
    return empty($name);
});

正如你所见, Collection 类允许你链式调用其它方法以执行流畅的映射和减少基础数组。通常,集合是不可变的,这意味着每个 Collection 方法都返回一个全新的 Collection 实例。

创建集合

如上所述,collect 辅助函数会为指定的数组返回一个新的 Illuminate\Support\Collection 实例。因此,我们可以非常容易的创建一个集合:

$collection = collect([1, 2, 3]);

技巧:Eloquent 查询结果总是返回 Collection 实例。

扩展集合

集合都是「可宏扩展」的, 它允许你在执行时将其它方法添加到 Collection 类。 Illuminate\Support\Collection 类的 macro 方法接受一个闭包,该闭包将在调用你的宏时执行。 宏闭包可以通过 $this访问集合的其他方法,就像它是集合类的真实方法一样。例如,以下代码将 toUpper 方法添加到 Collection 类中:

use Illuminate\Support\Collection;
use Illuminate\Support\Str;

Collection::macro('toUpper', function () {
    return $this->map(function ($value) {
        return Str::upper($value);
    });
});

$collection = collect(['first', 'second']);

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

通常,您应该在 service providerboot 方法中声明集合宏。

宏参数

如有必要,可以定义接受其他参数的宏:

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Str;

Collection::macro('toLocale', function ($locale) {
    return $this->map(function ($value) use ($locale) {
        return Lang::get($value, [], $locale);
    });
});

$collection = collect(['first', 'second']);

$translated = $collection->toLocale('es');

可用的方法

对于剩余的大部分集合文档,我们将讨论 Collection 类中可用的每个方法。请记住,所有这些方法都可以链式调用,以便流畅地操作底层数组。此外,几乎每个方法都会返回一个新的 Collection 实例,允许你在必要时保留集合的原始副本:

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
firstWhere
flatMap
flatten
flip
forget
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
pipeInto
pluck
pop
prepend
pull
push
put
random
reduce
reject
replace
replaceRecursive
reverse
search
shift
shuffle
skip
skipUntil
skipWhile
slice
some
sort
sortBy
sortByDesc
sortDesc
sortKeys
sortKeysDesc
splice
split
splitIn
sum
take
takeUntil
takeWhile
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 方法返回该集合所代表的底层数组:

collect([1, 2, 3])->all();

// [1, 2, 3]

average() #

avg 方法的别名.

avg() #

avg 方法 返回集合中所有项目的 平均值:

$average = collect([
    ['foo' => 10],
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 40]
])->avg('foo');

// 20

$average = collect([1, 1, 2, 4])->avg();

// 2

chunk() #

chunk 方法将集合分解为多个给定大小的较小集合:

$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->all();

// [[1, 2, 3, 4], [5, 6, 7]]

在使用 Bootstrap 这种栅格系统时, 视图 中特别有用. 想象一下你有个想在栅格显示的 Eloquent 模型:

@foreach ($products->chunk(3) as $chunk)
    <div class="row">
        @foreach ($chunk as $product)
            <div class="col-xs-4">{{ $product->name }}</div>
        @endforeach
    </div>
@endforeach

chunkWhile() #

chunkWhile 方法根据给定回调的求值将集合分解为多个更小的集合. $chunk 传递给闭包的变量可以用来检查前一个元素:

$collection = collect(str_split('AABBCCCD'));

$chunks = $collection->chunkWhile(function ($value, $key, $chunk) {
    return $value === $chunk->last();
});

$chunks->all();

// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]

collapse() {#collection-collapse}

collapse 方法将数组集合合并为单一的集合

$collection = collect([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]);

$collapsed = $collection->collapse();

$collapsed->all();

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

combine() {#collection-method}

combine 方法将集合的值作为键与另一个数组或集合的值结合在一起:

$collection = collect(['name', 'age']);

$combined = $collection->combine(['George', 29]);

$combined->all();

// ['name' => 'George', 'age' => 29]

collect() {#collection-method}

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]

技巧:当你有个 Enumerable 实例并需要一个非懒集合实例时,collect 方法相当有用。由于 collect()Enumerable 契约的一部分,你可以安全地使用它以获取一个 Collection 实例。

concat() {#collection-method}

concat 方法将给定的数组或集合的值附加到另一个集合的末尾:

$collection = collect(['John Doe']);

$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);

$concatenated->all();

// ['John Doe', 'Jane Doe', 'Johnny Doe']

contains() {#collection-method}

你也可以向 contains 传递一个闭包,来执行你的真值检验:

$collection = collect([1, 2, 3, 4, 5]);

$collection->contains(function ($value, $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 方法使用「严格」比较过滤。

containsStrict() {#collection-method}

这个方法和 contains 方法类似;但是它使用了「 严格 」比照来比较所有的值。

技巧:使用 Eloquent Collections 时,这个方法的行为会被修改。

count() {#collection-method}

count 方法返回集合内元素的总数量:

$collection = collect([1, 2, 3, 4]);

$collection->count();

// 4

countBy() {#collection-method}

The 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() {#collection-method}

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() {#collection-method}

dd方法用于打印集合元素并中断脚本执行:

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dd();

/*
    Collection {
        #items: array:2 [
            0 => "John Doe"
            1 => "Jane Doe"
        ]
    }
*/

如果你不想中断执行脚本,请使用 dump 方法替代。

diff() {#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 Collections 时,这个方法的行为会被修改。

diffAssoc() {#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]

diffKeys() {#collection-method}

diffKeys 方法和另外一个集合或 PHP array 的键(keys)进行比较,然后返回原集合中存在而指定集合中不存在键所对应的键 / 值对:

$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() {#collection-method}

dump方法用于打印集合项:

$collection = collect(['John Doe', 'Jane Doe']);

$collection->dump();

/*
    Collection {
        #items: array:2 [
            0 => "John Doe"
            1 => "Jane Doe"
        ]
    }
*/

如果要在打印集合后终止执行脚本,请使用 dd 方法代替。

duplicates() {#collection-method}

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() {#collection-method}

此方法与 duplicates 方法具有相同的签名;但是,所有值都以「严格」的方式进行比较。

each() {#collection-method}

each 方法用于循环集合项并将其传递到回调函数中:

$collection->each(function ($item, $key) {
    //
});

如果你想中断对集合项的循环,那么就在你的回调函数中返回 false

$collection->each(function ($item, $key) {
    if (/* condition */) {
        return false;
    }
});

eachSpread() {#collection-method}

eachSpread 方法用于循环集合项,将每个嵌套集合项的值传递给回调函数:

$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);

$collection->eachSpread(function ($name, $age) {
    //
});

你可以通过在回调函数里返回 false 来中断循环:

$collection->eachSpread(function ($name, $age) {
    return false;
});

every() {#collection-method}

every 方法可用于验证集合中的每一个元素是否通过指定的条件测试:

collect([1, 2, 3, 4])->every(function ($value, $key) {
    return $value > 2;
});

// false

如果集合为空 every 方法将返回 true :

$collection = collect([]);

$collection->every(function ($value, $key) {
    return $value > 2;
});

// true

except() {#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 集合会修改此方法的行为。

filter() {#collection-method}

filter 方法使用一个回调函数过滤集合中的元素,仅保留通过回调判断为真的值:

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->filter(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [3, 4]

如果没有提供回调, 则集合中所有等于 false 的元素将会被移除:

$collection = collect([1, 2, 3, null, false, '', 0, []]);

$collection->filter()->all();

// [1, 2, 3]

filter 相反,请查看 reject 方法。

first() {#collection-method}

first 方法返回回调函数中判断为真的第一个元素:

collect([1, 2, 3, 4])->first(function ($value, $key) {
    return $value > 2;
});

// 3

您也可以不使用任何参数去调用 first 方法,它将会返回集合中的第一个元素。 如果集合为空,null 将会被返回:

collect([1, 2, 3, 4])->first();

// 1

firstWhere() {#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]

flatMap() {#collection-method}

flatMap 方法遍历集合并将其中的每个值传递到给定的回调函数。可以通过回调函数修改集合项并返回它们,从而形成一个被修改过的新集合。然后,集合转化的数组是同级的:

$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() {#collection-method}

flatten 方法将多维集合转为一维集合:

$collection = collect([
    'name' => 'taylor',
    'languages' => [
        'php', 'javascript'
    ]
]);

$flattened = $collection->flatten();

$flattened->all();

// ['taylor', 'php', 'javascript'];

你可以选择性地传入「深度」参数:

$collection = collect([
    'Apple' => [
        [
            'name' => 'iPhone 6S',
            'brand' => 'Apple'
        ],
    ],
    'Samsung' => [
        [
            'name' => 'Galaxy S7',
            'brand' => 'Samsung'
        ],
    ],
]);

$products = $collection->flatten(1);

$products->values()->all();

/*
    [
        ['name' => 'iPhone 6S', 'brand' => 'Apple'],
        ['name' => 'Galaxy S7', 'brand' => 'Samsung'],
    ]
*/

在这个例子里,调用 flatten 时不传入深度参数的话也会将嵌套数组转成一维的,然后返回 ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung'] 。传入深度参数能让你限制设置返回数组的层数。

flip() {#collection-method}

flip 方法交换键与它对应的值:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$flipped = $collection->flip();

$flipped->all();

// ['taylor' => 'name', 'laravel' => 'framework']

forget() {#collection-method}

forget 方法通过指定键移除某个元素:

$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);

$collection->forget('name');

$collection->all();

// ['framework' => 'laravel']

注意:不像其它集合方法, forget 不返回修改过的集合; 它修改了被它调用的集合。

forPage() {#collection-method}

forPage 方法返回一个包含将会在给定页码中出现的项目的新集合。此方法接受页码做为它的第一个参数并且每页展示的项目做为第二个参数。

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);

$chunk = $collection->forPage(2, 3);

$chunk->all();

// [4, 5, 6]

get() {#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 'taylor@example.com';
});

// taylor@example.com

groupBy() {#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 ($item, $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 ($item) {
    return $item['roles'];
}], $preserveKeys = true);

/*
[
    1 => [
        'Role_1' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_2' => [
            20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
        ],
        'Role_3' => [
            10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
        ],
    ],
    2 => [
        'Role_1' => [
            30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
        ],
        'Role_2' => [
            40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
        ],
    ],
];
*/

has() {#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

implode() {#collection-method}

implode 方法连接集合中的元素。 它的参数取决于集合元素的类型。 如果集合中包含数组或对象,您应该传入您期望连接的属性的键, 并且您期望放置在值与值之间的「glue」字符串:

$collection = collect([
    ['account_id' => 1, 'product' => 'Desk'],
    ['account_id' => 2, 'product' => 'Chair'],
]);

$collection->implode('product', ', ');

// Desk, Chair

如果集合只包含简单的字符串或数字值, 您应该传入「glue」做为此方法的唯一参数:

collect([1, 2, 3, 4, 5])->implode('-');

// '1-2-3-4-5'

intersect() {#collection-method}

intersect 方法会从给定的 array 或集合移除一些在原始集合中不存在的值 。 返回结果将会保留原始集合的键:

$collection = collect(['Desk', 'Sofa', 'Chair']);

$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']

技巧:当使用 Eloquent 集合会修改此方法的行为。

intersectByKeys() {#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]

isEmpty() {#collection-method}

isEmpty 会返回 true ,如果集合为空; 否则 false 会被返回:

collect([])->isEmpty();

// true

isNotEmpty() {#collection-method}

isNotEmpty 方法返回 true 如果集合不为空; 否则, false 会被返回:

collect([])->isNotEmpty();

// false

join() {#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 '); // ''

keyBy() {#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 ($item) {
    return strtoupper($item['product_id']);
});

$keyed->all();

/*
    [
        'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
        'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
    ]
*/

keys() {#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']

last() {#collection-method}

last 方法返回集合中符合条件的最后一个元素:

collect([1, 2, 3, 4])->last(function ($value, $key) {
    return $value < 3;
});

// 2

您也可以不加参数调用 last 方法去获取集合的最后一个元素。 如果集合为空, null 会被返回:

collect([1, 2, 3, 4])->last();

// 4

macro() {#collection-method}

静态 macro 方法允许您在运行时去增加方法到 Collection 类。 更多信息请参考 扩展集合 文档。

make() {#collection-method}

静态 make 方法可以创建一个新的集合实例。请参照 创建集合 部分。

map() {#collection-method}

map方法遍历集合并将每一个值传入给定的回调函数。该回调函数可以任意修改集合项并返回,从而生成被修改过集合项的新集合:

$collection = collect([1, 2, 3, 4, 5]);

$multiplied = $collection->map(function ($item, $key) {
    return $item * 2;
});

$multiplied->all();

// [2, 4, 6, 8, 10]

注意:与其他大多数集合方法一样, map 会返回一个新的集合实例;它不会修改原集合。如果你想修改原集合,请使用 transform 方法。

mapInto() {#collection-method}

mapInto() 方法可以迭代集合,通过将值传递给构造函数来创建给定类的新实例:

class Currency
{
    /**
     * 创建新的 Currency 实例
     *
     * @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() {#collection-method}

mapSpread 方法可以迭代集合值,将每个嵌套项值给指定的回调函数。该回调函数可以自由修改该集合项并返回,从而生成被修改过集合项的新集合:

$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() {#collection-method}

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->all();

/*
    [
        'Sales' => ['John Doe', 'Jane Doe'],
        'Marketing' => ['Johnny Doe'],
    ]
*/

$grouped->get('Sales')->all();

// ['John Doe', 'Jane Doe']

mapWithKeys() {#collection-method}

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() {#collection-method}

max 方法返回指定键的最大值:

$max = collect([
    ['foo' => 10],
    ['foo' => 20]
])->max('foo');

// 20

$max = collect([1, 2, 3, 4, 5])->max();

// 5

median() {#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

merge() {#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']

mergeRecursive() {#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]

min() {#collection-method}

min 方法返回指定键的最小值:

$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');

// 10

$min = collect([1, 2, 3, 4, 5])->min();

// 1

mode() {#collection-method}

mode方法返回指定键的 众数值

$mode = collect([
    ['foo' => 10],
    ['foo' => 10],
    ['foo' => 20],
    ['foo' => 40]
])->mode('foo');

// [10]

$mode = collect([1, 1, 2, 4])->mode();

// [1]

nth() {#collection-method}

nth 方法创建由每 n 个元素取一个元素组成的新集合:

$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);

$collection->nth(4);

// ['a', 'e']

你也可以设置指定的偏移位置作为第二个参数:

$collection->nth(4, 1);

// ['b', 'f']

only() {#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 Collections 会被修改。

pad() {#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']

partition() {#collection-method}

partition 可以和 PHP 的 list 方法配合使用,利用回调返回是否为真,用来分开通过了指定条件以及未通过指定条件的元素:

$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() {#collection-method}

pipe 可以把集合放到回调参数中并返回回调的结果:

$collection = collect([1, 2, 3]);

$piped = $collection->pipe(function ($collection) {
    return $collection->sum();
});

// 6

pipeInto() {#collection-method}

pipeInto 方法创建一个给定类的新实例,并将集合传递给构造函数:

class ResourceCollection
{
    /**
     * Collection 实例.
     */
    public $collection;

    /**
     * 创建一个新的 ResourceCollection 实例。
     *
     * @param  Collection  $resource
     * @return void
     */
    public function __construct(Collection $collection)
    {
        $this->collection = $collection;
    }
}

$collection = collect([1, 2, 3]);

$resource = $collection->pipeInto(ResourceCollection::class);

$resource->collection->all();

// [1, 2, 3]

pluck() {#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([
    [
        'speakers' => [
            'first_day' => ['Rosa', 'Judith'],
            'second_day' => ['Angela', 'Kathleen'],
        ],
    ],
]);

$plucked = $collection->pluck('speakers.first_day');

$plucked->all();

// ['Rosa', 'Judith']

如果存在重复的键,则最后一个匹配元素将被插入到新的集合中:

$collection = collect([
    ['brand' => 'Tesla',  'color' => 'red'],
    ['brand' => 'Pagani', 'color' => 'white'],
    ['brand' => 'Tesla',  'color' => 'black'],
    ['brand' => 'Pagani', 'color' => 'orange'],
]);

$plucked = $collection->pluck('color', 'brand');

$plucked->all();

// ['Tesla' => 'black', 'Pagani' => 'orange']

pop() {#collection-method}

pop 从原集合返回并移除集合中的最后一项:

$collection = collect([1, 2, 3, 4, 5]);

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

prepend() {#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]

pull() {#collection-method}

pull 方法把指定键对应的值从集合中移除并返回:

$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);

$collection->pull('name');

// 'Desk'

$collection->all();

// ['product_id' => 'prod-100']

push() {#collection-method}

push 方法把数据值追加到集合尾部:

$collection = collect([1, 2, 3, 4]);

$collection->push(5);

$collection->all();

// [1, 2, 3, 4, 5]

put() {#collection-method}

put 方法在集合内设置给定的键和值:

$collection = collect(['product_id' => 1, 'name' => 'Desk']);

$collection->put('price', 100);

$collection->all();

// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]

random() {#collection-method}

random 方法从集合中返回一个随机值:

$collection = collect([1, 2, 3, 4, 5]);

$collection->random();

// 4 - (retrieved randomly)

你可以传入一个整数到 random 来指定要获取的随机值的数量。只要你显示地传递希望获取的集合值数量,那么数值的集合总会被返回:

$random = $collection->random(3);

$random->all();

// [2, 4, 5] - (retrieved randomly)

如果集合的项小于指定的数量,那么 random 方法会抛出 InvalidArgumentException 异常。

reduce() {#collection-method}

reduce 方法将每次迭代的结果传递给下一次迭代,直到集合缩减为单个值:

$collection = collect([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

reduce 方法也可以在关联集合里传递数组键给指定的回调:

$collection = collect([
    'usd' => 1400,
    'gbp' => 1200,
    'eur' => 1000,
]);

$ratio = [
    'usd' => 1,
    'gbp' => 1.37,
    'eur' => 1.22,
];

$collection->reduceWithKeys(function ($carry, $value, $key) use ($ratio) {
    return $carry + ($value * $ratio[$key]);
});

// 4264

reject() {#collection-method}

reject方法使用指定的回调函数过滤集合。如果回调函数返回 true 就会把对应的元素从集合中移除:

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->reject(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [1, 2]

reject 方法对应的方法是 filter

replace() {#collection-method}

replace 方法用法类似于 merge ;但是,replace 不仅可以覆盖匹配到的相同字符串键的元素,同时也可以覆盖匹配到数字键的元素:

$collection = collect(['Taylor', 'Abigail', 'James']);

$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);

$replaced->all();

// ['Taylor', 'Victoria', 'James', 'Finn']

replaceRecursive() {#collection-method}

这个方法使用类似 replace ,但是会以递归的形式将数组替换到具有相同键的元素中:

$collection = collect([
    'Taylor',
    'Abigail',
    [
        'James',
        'Victoria',
        'Finn'
    ]
]);

$replaced = $collection->replaceRecursive([
    'Charlie',
    2 => [1 => 'King']
]);

$replaced->all();

// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]

reverse() {#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',
    ]
*/

search() {#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 ($item, $key) {
    return $item > 5;
});

// 2

shift() {#collection-method}

shift 方法移除并返回集合的第一个元素:

$collection = collect([1, 2, 3, 4, 5]);

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

shuffle() {#collection-method}

shuffle 方法随机打乱元素:

$collection = collect([1, 2, 3, 4, 5]);

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (generated randomly)

skip() {#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]

skipUntil() {#collection-method}

skipUntil 方法将跳过元素直到给定的回调函数返回 true,然后返回集合中剩余的元素。

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipUntil(function ($item) {
    return $item >= 3;
});

$subset->all();

// [3, 4]

你也可以传递一个简单值到 skipUntil 方法来跳过所有元素直到找到给定的值:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipUntil(3);

$subset->all();

// [3, 4]

注意:如果没有找到指定的值或者回调函数始终没有返回 trueskipUntil 方法将返回一个空集合。

skipWhile() {#collection-method}

skipWhile 方法当回调函数返回 true 时跳过元素,然后返回集合中剩余的元素。

$collection = collect([1, 2, 3, 4]);

$subset = $collection->skipWhile(function ($item) {
    return $item <= 3;
});

$subset->all();

// [4]

注意:如果回调函数始终没有返回 trueskipWhile 方法将返回一个空集合。

slice() {#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 方法来重新建立索引。

some() {#collection-method}

contains 方法的别名。

sort() {#collection-method}

sort 方法对集合进行排序。排序后的集合会保留原数组的键,所以在这个例子我们将使用 values 方法将键重置为连续的数字索引:

$collection = collect([5, 3, 1, 2, 4]);

$sorted = $collection->sort();

$sorted->values()->all();

// [1, 2, 3, 4, 5]

如果你有更高级的排序需求,可以通过自己的算法将回调函数传递到 sort 。请参阅 PHP 文档的 uasort,这是集合的 sort 方法在底层所调用的。

技巧:如果你需要对嵌套数组或对象进行排序,请参照 sortBysortByDesc 方法。

sortBy() {#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],
    ]
*/

sort 方法接收 排序标志 作为第二个参数:

$collection = collect([
    ['title' => 'Item 1'],
    ['title' => 'Item 12'],
    ['title' => 'Item 3'],
]);

$sorted = $collection->sortBy('title', SORT_NATURAL);

$sorted->values()->all();

/*
    [
        ['title' => 'Item 1'],
        ['title' => 'Item 3'],
        ['title' => 'Item 12'],
    ]
*/

或者,你可以通过你自己的回调来决定如何排序集合的值:

$collection = collect([
    ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
    ['name' => 'Chair', 'colors' => ['Black']],
    ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);

$sorted = $collection->sortBy(function ($product, $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 ($a, $b) => $a['name'] <=> $b['name'],
    fn ($a, $b) => $b['age'] <=> $a['age'],
]);

$sorted->values()->all();

/*
    [
        ['name' => 'Abigail Otwell', 'age' => 32],
        ['name' => 'Abigail Otwell', 'age' => 30],
        ['name' => 'Taylor Otwell', 'age' => 36],
        ['name' => 'Taylor Otwell', 'age' => 34],
    ]
*/

sortByDesc() {#collection-method}

该方法与 sortBy 方法一样,但是会以相反的顺序来对集合进行排序:

sortDesc() {#collection-method}

该方法与 sort 方法一样,但是会以相反的顺序来对集合进行排序:

$collection = collect([5, 3, 1, 2, 4]);

$sorted = $collection->sortDesc();

$sorted->values()->all();

// [5, 4, 3, 2, 1]

sort 不同,你不能传递回调函数给 sortDesc。如果你想要使用回调函数,你可以使用 sort 颠倒比较。

sortKeys() {#collection-method}

sortKeys 方法通过底层关联数组的键来对集合进行排序:

$collection = collect([
    'id' => 22345,
    'first' => 'John',
    'last' => 'Doe',
]);

$sorted = $collection->sortKeys();

$sorted->all();

/*
    [
        'first' => 'John',
        'id' => 22345,
        'last' => 'Doe',
    ]
*/

sortKeysDesc() {#collection-method}

该方法与 sortKeys 方法一样,但是会以相反的顺序来对集合进行排序。

splice() {#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]

split() {#collection-method}

split 方法将集合按照给定的值拆分:

$collection = collect([1, 2, 3, 4, 5]);

$groups = $collection->split(3);

$groups->all();

// [[1, 2], [3, 4], [5]]

splitIn() {#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]]

sum() {#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 ($product) {
    return count($product['colors']);
});

// 6

take() {#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]

takeUntil() {#collection-method}

takeUntil 方法将返回集合中的元素,直到给定的回调函数返回 true:

$c ollection = collect([1, 2, 3, 4]);

$subset = $collection->takeUntil(function ($item) {
    return $item >= 3;
});

$subset->all();

// [1, 2]

你也可以传递一个简单值给 takeUntil 方法来获取元素,直到找到给定的值:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->takeUntil(3);

$subset->all();

// [1, 2]

注意:如果没有找到给定的值或者回调函数始终没有返回 truetakeUntil 方法将返回集合中所有的元素。

takeWhile() {#collection-method}

takeWhile 方法将返回集合中的元素直到给定的回调函数返回 false:

$collection = collect([1, 2, 3, 4]);

$subset = $collection->takeWhile(function ($item) {
    return $item < 3;
});

$subset->all();

// [1, 2]

注意:如果回调函数始终没有返回 falsetakeWhile 方法将返回集合中的所有元素。

tap() {#collection-method}

tap 方法将给定的回调函数传入该集合,允许你在特定的地点把「tap」插入集合里,并在不影响集合本身的情况下对集合项执行某些操作,然后集合通过 tap 方法返回:

collect([2, 4, 3, 1, 5])
    ->sort()
    ->tap(function ($collection) {
        Log::debug('Values after sorting', $collection->values()->all());
    })
    ->shift();

// 1

times() {#collection-method}

静态 times 方法通过调用给定次数的回调函数来创建新集合:

$collection = Collection::times(10, function ($number) {
    return $number * 9;
});

$collection->all();

// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

toArray() {#collection-method}

toArray 方法将集合转换成 PHP array。如果集合的值是Eloquent模型,那也会被转换成数组:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toArray();

/*
    [
        ['name' => 'Desk', 'price' => 200],
    ]
*/

注意: toArray 也会将 Arrayable 的实例、所有集合的嵌套对象转换为数组。如果你想获取原数组,可以使用 all 方法。

toJson() {#collection-method}

toJson 方法将集合转换成 JSON 字符串:

$collection = collect(['name' => 'Desk', 'price' => 200]);

$collection->toJson();

// '{"name":"Desk", "price":200}'

transform() {#collection-method}

transform 方法会遍历整个集合,并对集合中的每个元素都会调用其回调函数。集合中的元素将被替换为回调函数返回的值:

$collection = collect([1, 2, 3, 4, 5]);

$collection->transform(function ($item, $key) {
    return $item * 2;
});

$collection->all();

// [2, 4, 6, 8, 10]

注意:与大多数集合方法不同,transform 会修改集合本身。如果你想创建新集合,可以使用 map方法。

union() {#collection-method}

union 方法将给定数组添加到集合中。如果给定的数组含有与原集合一样的键,则首选原始集合的值:

$collection = collect([1 => ['a'], 2 => ['b']]);

$union = $collection->union([3 => ['c'], 1 => ['b']]);

$union->all();

// [1 => ['a'], 2 => ['b'], 3 => ['c']]

unique() {#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 ($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 Collections 时被修改。

uniqueStrict() {#collection-method}

这个方法与 unique 方法一样,然而,所有的值是用 「严格」模式来比较的。

unless() {#collection-method}

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() {#collection-method}

whenNotEmpty 方法的别名。

unlessNotEmpty() {#collection-method}

whenEmpty 方法的别名。

unwrap() {#collection-method}

静态 unwrap 方法返回集合内部的可用元素:

Collection::unwrap(collect('John Doe'));

// ['John Doe']

Collection::unwrap(['John Doe']);

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

values() {#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],
    ]
*/

when() {#collection-method}

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() {#collection-method}

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']

whenEmpty 方法可以传递第二个回调函数,当集合不是空时,它将会被执行:

$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() {#collection-method}

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();

// []

whenNotEmpty 可以传递第二个回调函数,当集合不是空时,它将会被执行:

$collection = collect();

$collection->whenNotEmpty(function ($collection) {
    return $collection->push('adam');
}, function ($collection) {
    return $collection->push('taylor');
});

$collection->all();

// ['taylor']

whenNotEmpty 相反的方法,请查看 whenEmpty 方法。

where() {#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'],
    ]
*/

whereStrict() {#collection-method}

此方法和 where 方法使用相似;但是它是「 严格 」模式去匹配值和类型。

whereBetween() {#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],
    ]
*/

whereIn() {#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 方法进行「 严格 」模式比较。

whereInStrict() {#collection-method}

此方法和 whereIn 方法使用相似;但是它是「 严格 」模式去匹配值和类型。

whereInstanceOf() {#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]

whereNotBetween() {#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],
    ]
*/

whereNotIn() {#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 方法进行「 严格 」模式比较。

whereNotInStrict() {#collection-method}

这个方法与 whereNotIn 方法类似;不同的是会使用「严格」模式比较。

whereNotNull() {#collection-method}

whereNotNull 方法从集合返回给定键的数值不为 null 的数据:

$collection = collect([
    ['name' => 'Desk'],
    ['name' => null],
    ['name' => 'Bookcase'],
]);

$filtered = $collection->whereNotNull('name');

$filtered->all();

/*
    [
        ['name' => 'Desk'],
        ['name' => 'Bookcase'],
    ]
*/

whereNull() {#collection-method}

whereNull 方法从集合返回给定键的数值是 null 的数据:

$collection = collect([
    ['name' => 'Desk'],
    ['name' => null],
    ['name' => 'Bookcase'],
]);

$filtered = $collection->whereNull('name');

$filtered->all();

/*
    [
        ['name' => null],
    ]
*/

wrap() {#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']

zip() {#collection-method}

zip 方法在与集合的值对应的索引处合并给定数组的值:

$collection = collect(['Chair', 'Desk']);

$zipped = $collection->zip([100, 200]);

$zipped->all();

// [['Chair', 100], ['Desk', 200]]

高阶信息

集合也提供对「 高阶信息 」的支持,即集合常见操作的快捷方式。支持高阶信息的集合方法有:
averageavgcontainseacheveryfilterfirstflatMapgroupBy, keyBymapmaxminpartitionrejectskipUntilskipWhilesomesortBysortByDescsumtakeUntiltakeWhile, 和 unique

每个高阶消息都可以作为集合上的动态属性进行访问。例如,each 高阶消息在集合中的每个对象上调用一个方法:

use App\Models\User;

$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

同样,我们可以使用 sum 高阶消息传递来收集 users 集合中的「 投票 」总数:

$users = User::where(‘group’, ‘Development’)->get();

return $users->sum->votes;

惰性集合

简介

注意:在进一步学习 Laravel 的惰性集合之前,我们先花点时间熟悉一下 PHP generators

为了补充已经很强大的 Collection 类, LazyCollection 类利用了 PHP 的 generators 允许你在保持低内存使用率的同时使用非常大的数据集。

例如,假设你的应用需要处理一个 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 ($lines) {
    return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
    // Process the log entry...
});

或者,假设你需要遍历 10000 个 Eloquent 模型。当使用传统的 Laravel 集合时,全部 10000 个 Eloquent 模型必须同时加载到内存中:

use App\Models\User;

$users = User::all()->filter(function ($user) {
    return $user->id > 500;
});

然而,查询构建器的 cursor 方法返回一个 LazyCollection 实例。这允许你对数据库只进行一次查询, 而且一次只能在内存中加载一个 Eloquent 模型。在此例中, filter 回调只有在我们实际逐个迭代每个用户之后才会执行,这样可以大幅度减少内存使用:

use App\Models\User;

$users = 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;
    }
});

The Enumerable 契约

Collection 类中几乎所有的方法在 LazyCollection 类中也能使用。这两个类都实现了 Illuminate\Support\Enumerable 契约,该契约定义了以下方法:

注意: LazyCollection 类不提供使集合变动的方法(如 shiftpopprepend 等)。

惰性集合方法

除了在 Enumerable 契约中定义的方法外, LazyCollection 类还包含以下方法:

takeUntilTimeout() {#collection-method}

takeUntilTimeout 方法返回新的惰性集合,它会在给定时间前去枚举集合值,之后集合将停止枚举:

$lazyCollection = LazyCollection::times(INF)
    ->takeUntilTimeout(now()->addMinute());

$lazyCollection->each(function ($number) {
    dump($number);

    sleep(1);
});

// 1
// 2
// ...
// 58
// 59

为了具体阐述此方法, 请设想一个使用游标从数据库提交发票的例子。你可以定义一个 计划任务 ,它每十五分钟执行一次,并且只执行发票提交操作的最大时间是14分钟:

use App\Models\Invoice;
use Illuminate\Support\Carbon;

Invoice::pending()->cursor()
    ->takeUntilTimeout(
        Carbon::createFromTimestamp(LARAVEL_START)->add(14, 'minutes')
    )
    ->each(fn ($invoice) => $invoice->submit());

tapEach() {#collection-method}

each 方法为集合中每一个元素调用给定回调时, tapEach 方法仅调用给定回调,因为这些元素正在逐个从列表中拉出:

// 没有任何输出
$lazyCollection = LazyCollection::times(INF)->tapEach(function ($value) {
    dump($value);
});

// 打印出三条数据
$array = $lazyCollection->take(3)->all();

// 1
// 2
// 3

remember() {#collection-method}

remember 方法返回一个新的惰性集合,这个集合已经记住(缓存)已枚举所有的值,当再次枚举该集合时不会获取它们:

// 没执行任何查询
$users = User::cursor()->remember();

//  执行了查询操作,并且前 5 个用户数据已经在数据库中查询完成
$users->take(5)->all();

// 前 5 个用户数据在缓存中获取,其余 15 个用户数据在数据库中查询.
$users->take(20)->all();

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/laravel/8.5/col...

译文地址:https://learnku.com/docs/laravel/8.5/col...

上一篇 下一篇
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
贡献者:10
讨论数量: 6
发起讨论 只看当前版本


panco
这个还挺厉害的
1 个点赞 | 0 个回复 | 问答 | 课程版本 5.7
Rxy-development
对数组使用 collect ()->sortByDesc ()->sortByDesc ()
0 个点赞 | 7 个回复 | 问答 | 课程版本 5.5
xingchen
这方法也忒多了,这如何记得住啊?
0 个点赞 | 4 个回复 | 问答 | 课程版本 5.6
MouseSoft
集合的 nth (4) 这个怎么理解呢?
0 个点赞 | 3 个回复 | 问答 | 课程版本 5.8
陈伯乐
最后的高阶消息传递看的不是太懂
0 个点赞 | 2 个回复 | 问答 | 课程版本 5.8