集合

简介

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 类添加其它方法。例如,如下代码为 Collection 类添加了一个 toUpper 方法:

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

通常来说,应该在 服务提供者 中声明集合的宏。

可用的方法

文档的后续内容中,我们会讨论 Collection 类每个可用的方法。注意,所有这些方法都可以进行链式调用流畅地操作底层数组。此外,几乎每个方法都会返回一个新的 Collection 实例,允许您在必要时保留集合的原始备份:

all
average
avg
chunk
collapse
combine
concat
contains
containsStrict
count
crossJoin
dd
diff
diffAssoc
diffKeys
dump
each
eachSpread
every
except
filter
first
firstWhere
flatMap
flatten
flip
forget
forPage
get
groupBy
has
implode
intersect
intersectByKeys
isEmpty
isNotEmpty
keyBy
keys
last
macro
make
map
mapInto
mapSpread
mapToGroups
mapWithKeys
max
median
merge
min
mode
nth
only
pad
partition
pipe
pluck
pop
prepend
pull
push
put
random
reduce
reject
reverse
search
shift
shuffle
slice
sort
sortBy
sortByDesc
sortKeys
sortKeysDesc
splice
split
sum
take
tap
times
toArray
toJson
transform
union
unique
uniqueStrict
unless
unwrap
values
when
where
whereStrict
whereIn
whereInStrict
whereInstanceOf
whereNotIn
whereNotInStrict
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->toArray();

// [[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

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

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

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

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

$combined->all();

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

concat()

concat 方法将给定数组或集合追加到集合最后:

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

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

$concatenated->all();

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

contains()

contains 方法判断集合是否包含给定项:

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

$collection->contains('Desk');

// true

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

// false

也可以传递键/值对给 contains 方法,判断给定的键值对是否存在于集合中:

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

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

// false

最后,还可以传递一个回调给 contains 方法执行自己的可信测试:

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

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

// false

contains 方法在检查项目值时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。可以使用 containsStrict 方法进行「严格」比较。

containsStrict()

此方法和 contains 方法有相同的参数;但是,所有值比较时都使用「严格」比较。

count()

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

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

$collection->count();

// 4

crossJoin()

crossJoin 方法将集合和给定数组或集合的值进行交叉连接,返回所有可能的排列组合:

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

$matrix = $collection->crossJoin(['a', 'b']);

$matrix->all();

/*
    [
        [1, 'a'],
        [1, 'b'],
        [2, 'a'],
        [2, 'b'],
    ]
*/

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

$matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']);

$matrix->all();

/*
    [
        [1, 'a', 'I'],
        [1, 'a', 'II'],
        [1, 'b', 'I'],
        [1, 'b', 'II'],
        [2, 'a', 'I'],
        [2, 'a', 'II'],
        [2, 'b', 'I'],
        [2, 'b', 'II'],
    ]
*/

dd()

dd 方法输出集合中的所有项并结束脚本执行:

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

$collection->dd();

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

如果不希望停止脚本执行,可以使用 dump 方法代替。

diff()

diff 方法将集合与另一个集合或原生 PHP 数组基于值进行比较。此方法会返回原集合中存在但给定集合中不存在的值:

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

$diff = $collection->diff([2, 4, 6, 8]);

$diff->all();

// [1, 3, 5]

diffAssoc()

diffAssoc 方法将集合与另一个集合或原生 PHP 数组基于键值对进行比较。此方法会返回原集合中存在但给定集合中不存在的键值对:

$collection = collect([
    'color' => 'orange',
    'type' => 'fruit',
    'remain' => 6
]);

$diff = $collection->diffAssoc([
    'color' => 'yellow',
    'type' => 'fruit',
    'remain' => 3,
    'used' => 6
]);

$diff->all();

// ['color' => 'orange', 'remain' => 6]

diffKeys()

diffKeys 方法将集合与另一个集合或原生 PHP 数组基于键进行比较。此方法会返回原集合中存在但给定集合中不存在的键值对:

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

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

$diff->all();

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

dump()

dump 方法会输出集合中的所有项:

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

$collection->dump();

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

如果要在输出集合后停止执行脚本,可以使用 dd 方法代替。

each()

each 方法迭代集合中的每一项,并将每一项传递给一个回调:

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

如果要在某一项时停止迭代,可以在回调中返回 false

$collection->each(function ($item, $key) {
    if (/* 一些条件 */) {
        return false;
    }
});

eachSpread()

eachSpread 方法迭代集合中的每一项,并将嵌套的每项的值传递到给定回调:

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

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

如果要在某一项时停止迭代,可以在回调中返回 false

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

every()

every 方法可用于验证集合中的所有元素都通过给定的可信测试:

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

// false

except()

except 方法返回集合中除了给定键以外的所有项:

$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);

$filtered = $collection->except(['price', 'discount']);

$filtered->all();

// ['product_id' => 1]

except 相反的方法,可以参见 only

filter()

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

first 方法返回集合中第一个通过给定的可信测试的元素:

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

// 3

也可以不带参数调用 first 方法来获取集合的第一个元素。如果集合为空,会返回 null

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

// 1

firstWhere()

firstWhere 方法返回集合中给定键/值对的第一个元素:

$collection = collect([
    ['name' => 'Regena', 'age' => 12],
    ['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]

flatMap()

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

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

flip 方法将集合的键与对应的值进行互换:

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

$flipped = $collection->flip();

$flipped->all();

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

forget()

forget 方法通过键从集合中移除指定项:

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

$collection->forget('name');

$collection->all();

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

不像大多数其它集合方法,forget 不返回一个新的修改后的集合;只改变调用的集合。

forPage()

forPage 方法返回一个将被显示在给定页码上的所有项的新集合。此方法接收一个页码作为其第一个参数,以及每页显示的项数作为其第二个参数:

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

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

$chunk->all();

// [4, 5, 6]

get()

get 方法返回给定键对应的项。如果键不存在,返回 null

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

$value = $collection->get('name');

// taylor

可以传递一个可选的默认值作为第二个参数:

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

$value = $collection->get('foo', 'default-value');

// default-value

甚至还可以传递一个回调作为默认值。当指定的键不存在时,会返回回调的结果:

$collection->get('email', function () {
    return 'default-value';
});

// default-value

groupBy()

groupBy 方法按给定键对集合中的所有项进行分组:

$collection = collect([
    ['account_id' => 'account-x10', 'product' => 'Chair'],
    ['account_id' => 'account-x10', 'product' => 'Bookcase'],
    ['account_id' => 'account-x11', 'product' => 'Desk'],
]);

$grouped = $collection->groupBy('account_id');

$grouped->toArray();

/*
    [
        '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->toArray();

/*
    [
        '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()

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

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

intersect 方法将从原集合中移除所有在给定数组或集合中不存在的值。最终的集合会保留原集合的键:

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

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

$intersect->all();

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

intersectByKeys()

intersectByKeys 方法将从原集合中移除所有在给定数组或集合中不存在的键:

$collection = collect([
    'serial' => 'UX301', 'type' => 'screen', 'year' => 2009
]);

$intersect = $collection->intersectByKeys([
    'reference' => 'UX404', 'type' => 'tab', 'year' => 2011
]);

$intersect->all();

// ['type' => 'screen', 'year' => 2009]

isEmpty()

isEmpty 方法会在集合为空时返回 true;否则,返回 false

collect([])->isEmpty();

// true

isNotEmpty()

isNotEmpty 方法会在集合不为空时返回 true;否则,返回 false

collect([])->isNotEmpty();

// false

keyBy()

keyBy 方法使用给定键作为集合的键。如果集合中有多项拥有相同的键,只有最后一个会出现在新集合中:

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

$keyed = $collection->keyBy('product_id');

$keyed->all();

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

也可以传递一个回调给此方法。回调返回作为集合的键的值:

$keyed = $collection->keyBy(function ($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()

keys 方法返回所有集合的键:

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

$keys = $collection->keys();

$keys->all();

// ['prod-100', 'prod-200']

last()

last 方法返回集合中最后一个通过给定的可信测试的元素:

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

// 2

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

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

// 4

macro()

静态的 macro 方法可以在运行时为 Collection 类添加方法。查看 扩展集合 文档了解更多信息。

make()

静态的 make 方法可以创建一个新的集合实例。参见 创建集合 一节。

map()

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

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

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

mapSpread 方法迭代集合中的每一项,并将嵌套的每项的值传递到给定回调。回调中可以自由修改并返回指定项,从而生成一个修改后的新集合。

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

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

$sequence = $chunks->mapSpread(function ($odd, $even) {
    return $odd + $even;
});

$sequence->all();

// [1, 5, 9, 13, 17]

mapToGroups()

mapToGroups 方法通过给定回调为集合所有项进行分组。回调返回一个包含单个键/值对的关联数组,从而生成一个对值进行分组后的新集合:

$collection = collect([
    [
        'name' => 'John Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Jane Doe',
        'department' => 'Sales',
    ],
    [
        'name' => 'Johnny Doe',
        'department' => 'Marketing',
    ]
]);

$grouped = $collection->mapToGroups(function ($item, $key) {
    return [$item['department'] => $item['name']];
});

$grouped->toArray();

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

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

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

mapWithKeys()

mapWithKeys 方法迭代集合中的每一项,并将每项的值传递到给定回调。回调返回一个包含单个键/值对的关联数组:

$collection = collect([
    [
        'name' => 'John',
        'department' => 'Sales',
        'email' => 'john@example.com'
    ],
    [
        'name' => 'Jane',
        'department' => 'Marketing',
        'email' => 'jane@example.com'
    ]
]);

$keyed = $collection->mapWithKeys(function ($item) {
    return [$item['email'] => $item['name']];
});

$keyed->all();

/*
    [
        'john@example.com' => 'John',
        'jane@example.com' => 'Jane',
    ]
*/

max()

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

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

// 20

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

// 5

median()

median 方法返回给定键的 中值

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

// 15

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

// 1.5

merge()

merge 方法将给定数组或集合与原集合合并。如果给定项的字符串键和原集合中的字符串键相同,给定项的值会被原集合中的值覆盖:

$collection = collect(['product_id' => 1, 'price' => 100]);

$merged = $collection->merge(['price' => 200, 'discount' => false]);

$merged->all();

// ['product_id' => 1, 'price' => 200, 'discount' => false]

如果给定项的键是数字,其值会被追加到集合的最后:

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

$merged = $collection->merge(['Bookcase', 'Door']);

$merged->all();

// ['Desk', 'Chair', 'Bookcase', 'Door']

min()

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

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

// 10

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

// 1

mode()

mode 方法返回给定键的 众值

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

// [10]

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

// [1]

nth()

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

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

$collection->nth(4);

// ['a', 'e']

可以传递一个可选的偏移作为第二个参数:

$collection->nth(4, 1);

// ['b', 'f']

only()

only 方法返回集合中在给定键中的所有项:

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

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

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

only 相反的方法,可以参见 except

pad()

pad 方法会使用给定数组填充数组,直到达到指定大小。此方法类似 PHP 函数 array_pad

要补齐到左侧,应该指定一个负的大小。如果给定大小的绝对值小于或等于数组长度,将不会进行补齐:

$collection = collect(['A', 'B', 'C']);

$filtered = $collection->pad(5, 0);

$filtered->all();

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

$filtered = $collection->pad(-5, 0);

$filtered->all();

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

partition()

partition 方法可以和 PHP 函数 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()

pipe 方法将集合传递给给定回调并返回结果:

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

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

// 6

pluck()

pluck 方法获取给定键的所有值:

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

$plucked = $collection->pluck('name');

$plucked->all();

// ['Desk', 'Chair']

也可以指定生成的集合的键:

$plucked = $collection->pluck('name', 'product_id');

$plucked->all();

// ['prod-100' => 'Desk', 'prod-200' => 'Chair']

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

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

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

$plucked->all();

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

pop()

pop 方法从集合中移除并返回最后一项:

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

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

prepend()

prepend 方法在集合的最开始添加一项:

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

$collection->prepend(0);

$collection->all();

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

也可以传递第二个参数设置添加项的键:

$collection = collect(['one' => 1, 'two' => 2]);

$collection->prepend(0, 'zero');

$collection->all();

// ['zero' => 0, 'one' => 1, 'two' => 2]

pull()

pop 方法从集合中移除并返回指定键对应的项:

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

$collection->pull('name');

// 'Desk'

$collection->all();

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

push()

push 方法在集合的最后追加一项:
The push method appends an item to the end of the collection:

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

$collection->push(5);

$collection->all();

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

put()

put 方法在集合中设置指定键和值:

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

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

$collection->all();

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

random()

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

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

$collection->random();

// 4 - (retrieved randomly)

可以传递一个可选的整数指定要随机获取的项数。当显式传递了希望接收的项数时会始终返回一个集合:

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

$random->all();

// [2, 4, 5] - (随机获取)

如果集合的总项数小于请求数,此方法会抛出一个 InvalidArgumentException

reduce()

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

reject()

reject 方法使用给定回调过滤集合。如果要从最后的集合中移除一项,应在回调中返回 true

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

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

$filtered->all();

// [1, 2]

reject 相反的方法,可以参见 filter

reverse()

reverse 方法反转集合中所有项的顺序,但会保留原来的键:

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

$reversed = $collection->reverse();

$reversed->all();

/*
    [
        4 => 'e',
        3 => 'd',
        2 => 'c',
        1 => 'b',
        0 => 'a',
    ]
*/

search()

search 方法用给定值在集合中搜索,如果找到了就返回对应的键。如果没有找到,返回 false

$collection = collect([2, 4, 6, 8]);

$collection->search(4);

// 1

搜索时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。要使用「严格」比较,将 true 作为第二个参数传递给此方法:

$collection->search('4', true);

// false

或者,可以传递自己的回调来搜索通过可信测试的第一项:

$collection->search(function ($item, $key) {
    return $item > 5;
});

// 2

shift()

shift 方法移除并返回集合的第一项:

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

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

shuffle()

shuffle 方法随机排列集合中的所有项:

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

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (随机生成)

slice()

slice 方法从集合中返回给定索引之后的部分:

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

$slice = $collection->slice(4);

$slice->all();

// [5, 6, 7, 8, 9, 10]

如果要限制返回部分的大小,可以将希望的大小作为第二个参数传递给此方法:

$slice = $collection->slice(4, 2);

$slice->all();

// [5, 6]

返回的部分会保留默认的键。如果不希望保留原来的键,可以使用 values 方法重建索引。

sort()

sort 方法对集合进行排序。排序后的集合保持原有数组的键。因此,在此示例中,我们使用 values 方法将键重置为连续的数字索引。

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

$sorted = $collection->sort();

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

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

如果有更高级的排序需求,可以将自己的算法作为回调传递给 sort。参阅 PHP 文档的 uasort,集合的 sort 方法在底层是调用的此函数。

如果要对嵌套的数组或对象进行排序,可以参数 sortBysortByDesc 方法。

sortBy()

sortBy 方法使用指定键对集合进行排序。排序后的集合保持原有数组的键。因此,在此示例中,我们使用 values 方法将键重置为连续的数字索引:

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

$sorted = $collection->sortBy('price');

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

/*
    [
        ['name' => 'Chair', 'price' => 100],
        ['name' => 'Bookcase', 'price' => 150],
        ['name' => 'Desk', 'price' => 200],
    ]
*/

也可以传递自己的回调来决定如何对集合的值进行排序:

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

sortByDesc()

此方法和 sortBy 有相同的参数,但是会按相反的顺序进行排序。

sortKeys()

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

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

$sorted = $collection->sortKeys();

$sorted->all();

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

sortKeysDesc()

此方法和 sortKeys 有相同的参数,但是会按相反的顺序进行排序。

splice()

splice 方法从集合中移除并返回给定索引之后的部分:

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

$chunk = $collection->splice(2);

$chunk->all();

// [3, 4, 5]

$collection->all();

// [1, 2]

可以传递第二个参数来限制大小:

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

$chunk = $collection->splice(2, 1);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 4, 5]

此外,还可以传递包含新的项的第三个参数,用来替换集合中移除的项:

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

$chunk = $collection->splice(2, 1, [10, 11]);

$chunk->all();

// [3]

$collection->all();

// [1, 2, 10, 11, 4, 5]

split()

split 方法将集合拆分成指定个数的组:

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

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

$groups->toArray();

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

sum()

sum 方法返回集合中所有项的和:

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

// 15

如果集合中包含嵌套的数组或对象,应该传递一个键指定要相加的值:

$collection = collect([
    ['name' => 'JavaScript: The Good Parts', 'pages' => 176],
    ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);

$collection->sum('pages');

// 1272

此外,还可以传递自己的回调来决定要相加的集合的值:

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

$collection->sum(function ($product) {
    return count($product['colors']);
});

// 6

take()

take 方法返回一个指定项数的新集合:

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

$chunk = $collection->take(3);

$chunk->all();

// [0, 1, 2]

也可以传递一个负整数,从集合的最后取指定项数:

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

$chunk = $collection->take(-2);

$chunk->all();

// [4, 5]

tap()

tap 方法将集合传递给指定回调,允许在指定位置访问集合并对其中的项进行不会影响集合本身的操作:

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

// 1

times()

静态的 times 方法按给定的总次数调用回调,创建一个新集合:

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

$collection->all();

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

此方法在工厂中创建 Eloquent 模型时会很有用:

$categories = Collection::times(3, function ($number) {
    return factory(Category::class)->create(['name' => 'Category #'.$number]);
});

$categories->all();

/*
    [
        ['id' => 1, 'name' => 'Category #1'],
        ['id' => 2, 'name' => 'Category #2'],
        ['id' => 3, 'name' => 'Category #3'],
    ]
*/

toArray()

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

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

$collection->toArray();

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

toArray 也会将所有集合嵌套的对象转换为数组。如果要获取底层原始的数组,可以使用 all 方法代替。

toJson()

toJson 方法将集合转换为 JSON 序列化的字符串:

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

$collection->toJson();

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

transform()

transform 方法迭代集合中的每一项,并将每个值传递给给定回调。集合中的项会被回调返回的值替换:

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

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

$collection->all();

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

不像大多数其它集合方法,transform 改变集合本身;如果希望创建一个新集合代替,可以使用 map 方法。

union()

union 方法添加给定数组到集合。如果给定数组包含原集合中已经存在的键,会保留原集合中的值:

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

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

$union->all();

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

unique()

unique 方法返回集合中的唯一项。返回的集合保持原数组的键。因此,在此示例中,我们使用 values 方法将键重置为连续的数字索引。

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

$unique = $collection->unique();

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

// [1, 2, 3, 4]

如果处理嵌套的数组或对象,可以指定用来判断的唯一键:

$collection = collect([
    ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
    ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
    ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
    ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);

$unique = $collection->unique('brand');

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

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

也可以使用自己的回调决定唯一键:

$unique = $collection->unique(function ($item) {
    return $item['brand'].$item['type'];
});

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

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

unique 方法在检查项目值时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。可以使用 uniqueStrict 方法进行「严格」比较。

uniqueStrict()

此方法和 unique 方法有相同的参数;但是,所有值比较时都使用「严格」比较。

unless()

unless 方法会执行给定的回调,除非传递给此方法的第一个参数的值为 true

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

$collection->unless(true, function ($collection) {
    return $collection->push(4);
});

$collection->unless(false, function ($collection) {
    return $collection->push(5);
});

$collection->all();

// [1, 2, 3, 5]

unless 相反的方法,可以参见 when

unwrap()

静态的 unwrap 方法会在适用时从给定的值中返回集合底层的所有项:

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

// ['John Doe']

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

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

values()

values 方法返回将键重置为连续的整数的新集合:

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

$values = $collection->values();

$values->all();

/*
    [
        0 => ['product' => 'Desk', 'price' => 200],
        1 => ['product' => 'Desk', 'price' => 200],
    ]
*/

when()

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

where()

where 方法通过给定的键/值对过滤集合:

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

$filtered = $collection->where('price', 100);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

where 方法在检查项目值时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。可以使用 whereStrict 方法进行「严格」比较。

whereStrict()

此方法和 where 方法有相同的参数;但是,所有值比较时都使用「严格」比较。

whereIn()

whereIn 方法通过包含在给定数组中的键/值对过滤集合:

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

$filtered = $collection->whereIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Bookcase', 'price' => 150],
        ['product' => 'Desk', 'price' => 200],
    ]
*/

whereIn 方法在检查项目值时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。可以使用 whereInStrict 方法进行「严格」比较。

whereInStrict()

此方法和 whereIn 方法有相同的参数;但是,所有值比较时都使用「严格」比较。

whereInstanceOf()

whereInstanceOf 方法通过给定类的类型过滤集合:

$collection = collect([
    new User,
    new User,
    new Post,
]);

return $collection->whereInstanceOf(User::class);

whereNotIn()

whereNotIn 方法通过不包含在给定数组中的键/值对过滤集合:

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

$filtered = $collection->whereNotIn('price', [150, 200]);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 100],
        ['product' => 'Door', 'price' => 100],
    ]
*/

whereNotIn 方法在检查项目值时使用「宽松」比较,意味着整数值字符串会被认为与有相同值的整数相等。可以使用 whereNotInStrict 方法进行「严格」比较。

whereNotInStrict()

此方法和 whereNotIn 方法有相同的参数;但是,所有值比较时都使用「严格」比较。

wrap()

静态的 wrap 方法会在适用时把给定的值包装到集合中:

$collection = Collection::wrap('John Doe');

$collection->all();

// ['John Doe']

$collection = Collection::wrap(['John Doe']);

$collection->all();

// ['John Doe']

$collection = Collection::wrap(collect('John Doe'));

$collection->all();

// ['John Doe']

zip()

zip 方法将给定数组的值与原集合对应索引的值合并到一起:

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

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

$zipped->all();

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

高阶信息

集合也支持「高阶信息(Higher Order Messages)」,即在集合上用快捷操作处理常用操作。支持高阶信息的集合方法有:averageavgcontainseacheveryfilterfirstflatMapgroupBykeyBymapmaxminpartitionrejectsortBysortByDescsumunique

每个高阶信息都可以在集合实例上通过动态属性获取。例如,我们使用 each 高阶信息对集合中的每个对象调用一个方法:

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

$users->each->markAsVip();

同样的,我们可以使用 sum 高阶信息获取集合中所有用户的「投票」总数:

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

return $users->sum->votes;