集合

介绍

Illuminate\Support\Collection 类为处理数据数组提供了一个流畅、方便的包装器。 例如,查看以下代码。 我们将使用 collect 助手从数组中创建一个新的集合实例,对每个元素运行 strtoupper 函数,然后删除所有空元素:

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

如你所见,Collection 类允许你链接其方法以执行流畅的映射和减少底层数组。一般来说,集合是不可变的,这意味着每个 Collection 方法都会返回一个全新的 Collection 实例。

创建集合

如上所述,collect 帮助器为给定数组返回一个新的 Illuminate\Support\Collection 实例。因此,创建一个集合非常简单:

$collection = collect([1, 2, 3]);
技巧:Eloquent 查询的结果总是作为 Collection 实例返回。

扩展集合

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

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

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

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

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

通常,你应该在服务提供者boot 方法中声明集合宏。

宏参数

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

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

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

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

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

可用的方法

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

all
average
avg
chunk
chunkWhile
collapse
collect
combine
concat
contains
containsOneItem
containsStrict
count
countBy
crossJoin
dd
diff
diffAssoc
diffKeys
doesntContain
dump
duplicates
duplicatesStrict
each
eachSpread
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
pipe
pipeInto
pipeThrough
pluck
pop
prepend
pull
push
put
random
range
reduce
reduceSpread
reject
replace
replaceRecursive
reverse
search
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

 

方法列表

all() {.collection-method .first-collection-method}

all 方法返回由集合表示的底层数组:

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

// [1, 2, 3]

average() {.collection-method}

avg 方法的别名。

avg() {.collection-method}

avg 方法返回给定键的 平均值

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

// 20

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

// 2

chunk() {.collection-method}

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

chunkWhile() {.collection-method}

chunkWhile 方法根据给定回调的评估将集合分成多个更小的集合。传递给闭包的 $chunk 变量可用于检查前一个元素:

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

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

$chunks->all();

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

 

collapse() {.collection-method}

collapse 方法将数组集合折叠成一个单一的平面集合:

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

$collapsed = $collection->collapse();

$collapsed->all();

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

collect() {.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 实例。

combine() {.collection-method}

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

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

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

$combined->all();

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

concat() {.collection-method}

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

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

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

$concatenated->all();

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

concat 方法在数字上重新索引连接到原始集合上的项目的键。要维护关联集合中的键,请参阅 merge 方法。

contains() {.collection-method}

contains 方法确定集合是否包含给定项目。你可以将闭包传递给 contains 方法,以确定集合中是否存在与给定真值测试匹配的元素:

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

$collection->contains(function (int $value, int $key) {
    return $value > 5;
});

// false

或者,你可以将字符串传递给 contains 方法,以确定集合是否包含给定的项目值:

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

$collection->contains('Desk');

// true

$collection->contains('New York');

// false

你还可以将键/值对传递给 contains 方法,该方法将确定给定对是否存在于集合中:

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Chair', 'price' => 100],
]);

$collection->contains('product', 'Bookcase');

// false

contains 方法在检查项目值时使用“松散”比较,这意味着具有整数值的字符串将被视为等于具有相同值的整数。使用 containsStrict 方法使用“严格”比较进行过滤。

对于 contains 的逆操作,请参见 doesntContain 方法。

containsOneItem() {.collection-method}

containsOneItem 方法决定了集合是否包含一个项目。

collect([])->containsOneItem();

// false

collect(['1'])->containsOneItem();

// true

collect(['1', '2'])->containsOneItem();

// false

containsStrict() {.collection-method}

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

技巧:使用 Eloquent Collections 时会修改此方法的行为。

count() {.collection-method}

count 方法返回集合中的项目总数:

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

$collection->count();

// 4

countBy() {.collection-method}

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 (string $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 进行比较。此方法将返回给定集合中不存在的原始集合中的键/值对:

$collection = collect([
    'one' => 10,
    'two' => 20,
    'three' => 30,
    'four' => 40,
    'five' => 50,
]);

$diff = $collection->diffKeys([
    'two' => 2,
    'four' => 4,
    'six' => 6,
    'eight' => 8,
]);

$diff->all();

// ['one' => 10, 'three' => 30, 'five' => 50]

doesntContain() {.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 方法在检查项目值时使用「松散」比较,这意味着具有整数值的字符串将被视为等于具有相同值的整数。

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 = collect([1, 2, 3, 4]);

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

如果你想停止遍历这些项目,你可以从你的闭包中返回 false

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

eachSpread() {.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;
});

every() {.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

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 Collections 时被修改。

filter() {.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 方法。

first() {.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

firstOrFail() {.collection-method}

firstOrFail 方法与 first 方法相同;但是,如果没有找到结果,将抛出 Illuminate/Support/ItemNotFoundException 异常。

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

// Throws ItemNotFoundException...

你也可以调用 firstOrFail 方法,没有参数,以获得集合中的第一个元素。如果集合是空的,将抛出一个 Illuminate\Support\ItemNotFoundException 异常。

collect([])->firstOrFail();

// Throws ItemNotFoundException...

firstWhere() {.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 (array $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'];

如有必要,你可以向 flatten 方法传递一个「深度」参数:

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

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

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

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

在此示例中,调用 flatten 而不提供深度也会使嵌套数组变平,从而导致 ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']。提供深度允许你指定嵌套数组将被展平的级别数。

flip() {.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 (array $item, int $key) {
    return substr($item['account_id'], -3);
});

$grouped->all();

/*
    [
        'x10' => [
            ['account_id' => 'account-x10', 'product' => 'Chair'],
            ['account_id' => 'account-x10', 'product' => 'Bookcase'],
        ],
        'x11' => [
            ['account_id' => 'account-x11', 'product' => 'Desk'],
        ],
    ]
*/

多个分组标准可以作为数组传递。每个数组元素将应用于多维数组中的相应级别:

$data = new Collection([
    10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']],
    20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']],
    30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']],
    40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']],
]);

$result = $data->groupBy(['skill', function (array $item) {
    return $item['roles'];
}], preserveKeys: true);

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

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

hasAny() {.collection-method}

hasAny 方法确定在集合中是否存在任何给定的键。

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

$collection->hasAny(['product', 'price']);

// true

$collection->hasAny(['name', 'price']);

// false

implode() {.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

intersect() {.collection-method}

intersect 方法从原始集合中删除任何不存在于给定 array 或集合中的值。生成的集合将保留原始集合的键:

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

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

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']
技巧:使用 Eloquent Collections 时会修改此方法的行为。

intersectAssoc() {.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']

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 (array $item, int $key) {
    return strtoupper($item['product_id']);
});

$keyed->all();

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

keys() {.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 (int $value, int $key) {
    return $value < 3;
});

// 2

你也可以调用不带参数的last方法来获取集合中的最后一个元素。如果集合为空,则返回 null

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

// 4

lazy() {.collection-method}

 

lazy 方法从底层的项目数组中返回一个新的 LazyCollection 实例。

$lazyCollection = collect([1, 2, 3, 4])->lazy();

get_class($lazyCollection);

// Illuminate\Support\LazyCollection

$lazyCollection->all();

// [1, 2, 3, 4]

当你需要对一个包含许多项目的巨大 Collection 进行转换时,这一点特别有用。

$count = $hugeCollection
    ->lazy()
    ->where('country', 'FR')
    ->where('balance', '>', '100')
    ->count();

通过将集合转换为 LazyCollection,我们避免了分配大量的额外内存。虽然原始集合仍然在内存中保留 它的 值,但后续的过滤器不会。因此,在过滤集合的结果时,几乎没有额外的内存被分配。

 

macro() {.collection-method}

静态macro()方法允许你在运行时向「集合」类添加方法。有关详细信息,请参阅有关 扩展集合 的文档。

make() {.collection-method}

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

map() {.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 方法。

mapInto() {.collection-method}

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

class Currency
{
    /**
     * Create a new currency instance.
     */
    function __construct(
        public string $code
    ) {}
}

$collection = collect(['USD', 'EUR', 'GBP']);

$currencies = $collection->mapInto(Currency::class);

$currencies->all();

// [Currency('USD'), Currency('EUR'), Currency('GBP')]

mapSpread() {.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]

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 (array $item, int $key) {
    return [$item['department'] => $item['name']];
});

$grouped->all();

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

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

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

mapWithKeys() {.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 (array $item, int $key) {
    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 值):

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

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 数组解构相结合,以将通过给定真值测试的元素与未通过的元素分开:

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

pipe() {.collection-method}

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

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

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

// 6

pipeInto() {.collection-method}

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

class ResourceCollection
{
    /**
     * Create a new ResourceCollection instance.
     */
    public function __construct(
      public Collection $collection,
    ) {}
}

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

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

$resource->collection->all();

// [1, 2, 3]

 

pipeThrough() {.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

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

pop() {.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]

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

random 方法也接受一个闭包,它将接收当前集合实例。

use Illuminate\Support\Collection;

$random = $collection->random(fn (Collection $items) => min(10, count($items)));

$random->all();

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

range() {.collection-method}

range 方法返回一个包含指定范围之间整数的集合:

$collection = collect()->range(3, 6);

$collection->all();

// [3, 4, 5, 6]

reduce() {.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

reduceSpread() {.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());

reject() {.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 方法。

replace() {.collection-method}

$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 (int $item, int $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]

你可以将整数传递给 shift 方法以从集合的开头删除并返回多个项目:

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

$collection->shift(3);

// collect([1, 2, 3])

$collection->all();

// [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 (int $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 (int $item) {
    return $item <= 3;
});

$subset->all();

// [4]
注意:如果回调从未返回 falseskipWhile 方法将返回一个空集合。

 

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 方法来重新索引它们。

sliding() {.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]]

sole() {.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

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]

如果你的排序需求更高级,你可以使用自己的算法将回调传递给「排序」。参考 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],
    ]
*/

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],
    ]
*/

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 方法具有相同的签名,但将以相反的顺序对集合进行排序。

sortKeysUsing() {.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 文档,这是 PHP 函数 sortKeysUsing 方法在内部使用。

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 (array $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

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

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

$subset->all();

// [1, 2]

你还可以将一个简单的值传递给 takeUntil 方法以获取项目,直到找到给定值:

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

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

$subset->all();

// [1, 2]
注意:如果未找到给定值或回调从未返回 true,则 takeUntil 方法将返回集合中的所有项目。

takeWhile() {.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 方法将返回集合中的所有项目。

tap() {.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

times() {.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]

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 (int $item, int $key) {
    return $item * 2;
});

$collection->all();

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

undot() {.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",
        ],
    ]
*/

union() {.collection-method}

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

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

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

$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 (array $item) {
    return $item['brand'].$item['type'];
});

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

/*
    [
        ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
        ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
        ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
        ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
    ]
*/

unique 方法在检查项目值时使用「宽松」模式比较,意味着具有整数值的字符串将被视为等于相同值的整数。你可以使用 uniqueStrict 方法做「严格」模式比较。

技巧:这个方法的行为在使用 Eloquent 集合 时被修改。

uniqueStrict() {.collection-method}

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

unless() {.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 方法。

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'

value() {.collection-method}

value 方法从集合的第一个元素中检索一个给定的值。

$collection = collect([
    ['product' => 'Desk', 'price' => 200],
    ['product' => 'Speaker', 'price' => 400],
]);

$value = $collection->value('price');

// 200

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 时,将执行给定的回调函数。
集合实例和给到 when 方法的第一个参数将被提供给闭包。

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

$collection->when(true, function (Collection $collection, int $value) {
    return $collection->push(4);
});

$collection->when(false, function (Collection $collection, int $value) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 4]

可以将第二个回调传递给该 when 方法。当给 when 方法的第一个参数计算结果为 false 时,将执行第二个回调:

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

$collection->when(false, function (Collection $collection, int $value) {
    return $collection->push(4);
}, function (Collection $collection) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

when 相反的方法,请查看 unless 方法。

whenEmpty() {.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 方法。

whenNotEmpty() {.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 方法。

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 方法在检查项目值时使用 "loose" 比较,这意味着具有整数值的字符串将被视为等于相同值的整数。使用 whereInStrict 方法使用「strict」比较进行过滤。

whereInStrict() {.collection-method}

此方法与 whereIn 方法具有相同的签名;但是,所有值都使用「strict」比较进行比较。

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 方法在检查项目值时使用「loose」比较,这意味着具有整数值的字符串将被视为等于具有相同值的整数。使用 whereNotInStrict 方法使用「strict」比较进行过滤。

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

Higher Order Messages

集合也提供对「高阶消息传递」的支持,即集合常见操作的快捷方式。支持高阶消息传递的集合方法有: averageavgcontainseacheveryfilterfirstflatMapgroupBykeyBymapmaxminpartitionrejectskipUntilskipWhilesomesortBysortByDescsumtakeUntiltakeWhileunique

 

每个高阶消息都可以作为集合实例上的动态属性进行访问。例如,让我们使用 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 的 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 (array $lines) {
    return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
    // Process the log entry...
});

或者,假设你需要遍历 10,000 个 Eloquent 模型。使用传统 Laravel 集合时,所有 10,000 个 Eloquent 模型必须同时加载到内存中:

use App\Models\User;

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

但是,查询构建器的 cursor 方法返回一个 LazyCollection 实例。这允许你仍然只对数据库运行一个查询,而且一次只在内存中加载一个 Eloquent 模型。在这个例子中,filter 回调在我们实际单独遍历每个用户之前不会执行,从而可以大幅减少内存使用量:

use App\Models\User;

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

foreach ($users as $user) {
    echo $user->id;
}

创建惰性集合

要创建惰性集合实例,你应该将 PHP 生成器函数传递给集合的 make 方法:

use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
    $handle = fopen('log.txt', 'r');

    while (($line = fgets($handle)) !== false) {
        yield $line;
    }
});

枚举契约

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

注意:改变集合的方法(例如 shiftpopprepend 等)在 LazyCollection 类中可用。

 

惰性集合方法

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

takeUntilTimeout() {.collection-method}

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

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

$lazyCollection->each(function (int $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) => $invoice->submit());

tapEach() {.collection-method}

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

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

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

// 1
// 2
// 3

remember() {.collection-method}

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

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

//  执行了查询操作
// The first 5 users are hydrated from the database...
$users->take(5)->all();

// 前 5 个用户数据从缓存中获取
// The rest are hydrated from the database...
$users->take(20)->all();