Коллекции
Введение
Класс Illuminate\Support\Collection
предоставляет гибкую и удобную обёртку для работы с массивами данных. Например, посмотрите на следующий код. Мы будем использовать хелпер collect
, чтобы создать новый экземпляр коллекции из массива, выполним функцию strtoupper
для каждого элемента, а затем удалим все пустые элементы:
$collection = collect(['taylor', 'abigail', null])->map(function ($name) {
return strtoupper($name);
})
->reject(function ($name) {
return empty($name);
});
Как видите, класс Collection
позволяет использовать методы для совершения операций типа map (обработка каждого элемента) и reduce (получение новых структур данных исходя из элементов массива) исходного массива. Коллекции иммутабельны, неизменны, то есть каждый метод класса Collection
возвращает совершенно новый экземпляр Collection
.
Создание коллекций
Как упоминалось выше, хелпер collect
возвращает новый экземпляр класса Illuminate\Support\Collection
для заданного массива. Поэтому создать коллекцию очень просто:
$collection = collect([1, 2, 3]);
Результаты запросов Eloquent всегда возвращаются в виде экземпляров класса
Collection
.
Расширение коллекций
Коллекции могут содержать макросы, что позволяет во время выполнения добавлять дополнительные методы для класса Collection
. Например, следующий код добавляет метод toUpper
в класс Collection
:
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
Collection::macro('toUpper', function () {
return $this->map(function ($value) {
return Str::upper($value);
});
});
$collection = collect(['first', 'second']);
$upper = $collection->toUpper();
// ['FIRST', 'SECOND']
Как правило, вы должны объявлять макросы коллекции в сервис-провайдере.
Доступные методы
В остальной части данной документации, мы будем обсуждать каждый метод, доступный в классе Collection
. Помните, все эти методы могут использоваться один за другим для гибкого управления заданным массивом. Кроме того, почти каждый метод возвращает новый экземпляр класса Collection
, позволяя вам при необходимости сохранить оригинал коллекции:
all average avg chunk collapse collect combine contains containsStrict count countBy diff diffAssoc diffKeys dump duplicates duplicatesStrict each every except filter first flatMap flatten flip forget forPage get groupBy has implode intersect intersectKey isEmpty isNotEmpty join keyBy keys last map mapWithKeys max median merge mergeRecursive min mode nth only partition pipe pluck pop prepend pull push put random reduce reject replace replaceRecursive reverse search shift shuffle skip slice some sort sortBy sortByDesc sortKeys sortKeysDesc splice split sum take tap times toArray toJson transform union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict whereNotNull whereNull 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->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()
{#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]
combine()
{#collection-method}
Метод combine
комбинирует ключи коллекции со значениями другого массива или коллекции:
$collection = collect(['name', 'age']);
$combined = $collection->combine(['George', 29]);
$combined->all();
// ['name' => 'George', 'age' => 29]
collect()
{#collection-method}
Метод collect
возвращает экземпляр Collection
со значениями переданного массива:
$collectionA = collect([1, 2, 3]);
$collectionB = $collectionA->collect();
$collectionB->all();
// [1, 2, 3]
Метод collect
можно использовать для конвертации ленивых коллекций в обычные:
$lazyCollection = LazyCollection::make(function () {
yield 1;
yield 2;
yield 3;
});
$collection = $lazyCollection->collect();
get_class($collection);
// 'Illuminate\Support\Collection'
$collection->all();
// [1, 2, 3]
Метод
collect
особенно полезен когда у вас есть экземплярEnumerable
и вам нужна неленивая коллекция. Посколькуcollect ()
является частью контрактаEnumerable
, вы можете безопасно использовать его для получения экземпляраCollection
concat()
{#collection-method}
Метод concat
добавляет заданные значения массива или коллекции в конец коллекции:
$collection = collect(['John Doe']);
$concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']);
$concatenated->all();
// ['John Doe', 'Jane Doe', 'Johnny Doe']
contains()
{#collection-method}
Метод contains
определяет, содержит ли коллекция заданное значение:
$collection = collect(['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()
{#collection-method}
Этот метод использует ту же сигнатуру, как и метод contains
; однако, все значения сравниваются с использованием строгого сравнения.
Поведение этого метода в коллекциях Eloquent изменено.
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 ($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
сравнивает одну коллекцию с другой коллекцией или с простым массивом, основываясь на его значениях. Этот метод вернёт те значения исходной коллекции, которых нет в переданной для сравнения коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$diff = $collection->diff([2, 4, 6, 8]);
$diff->all();
// [1, 3, 5]
Поведение этого метода в коллекциях Eloquent изменено.
diffAssoc()
{#collection-method}
Метод diffAssoc
сравнивает коллекцию с другой коллекцией или простым массивом, основываясь на ключах и значениях. Этот метод вернёт те пары ключ/значение исходной коллекции, которых нет в переданной для сравнения коллекции:
$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
сравнивает одну коллекцию с другой коллекцией или с простым массивом на основе их ключей. Этот метод вернёт те пары ключ/значение из исходной коллекции, которых нет в переданной для сравнения коллекции:
$collection = collect([
'one' => 10,
'two' => 20,
'three' => 30,
'four' => 40,
'five' => 50,
]);
$diff = $collection->diffKeys([
'two' => 2,
'four' => 4,
'six' => 6,
'eight' => 8,
]);
$diff->all();
// ['one' => 10, 'three' => 30, 'five' => 50]
dump()
{#collection-method}
Метод dump
сбрасывает элементы коллекции:
$collection = collect(['John Doe', 'Jane Doe']);
$collection->dump();
/*
Collection {
#items: array:2 [
0 => "John Doe"
1 => "Jane Doe"
]
}
*/
Если вы хотите прекратить выполнение сценария после сброса коллекции, используйте вместо этого метод dd
.
duplicates()
{#collection-method}
Метод duplicates
определяет и возвращает дубликаты в коллекции:
$collection = collect(['a', 'b', 'a', 'c', 'b']);
$collection->duplicates();
// [2 => 'a', 4 => 'b']
Если коллекция содержит массивы или объекты, вы можете указать название ключа, по которому будут определяться дубликаты:
$employees = collect([
['email' => 'abigail@example.com', 'position' => 'Developer'],
['email' => 'james@example.com', 'position' => 'Designer'],
['email' => 'victoria@example.com', 'position' => 'Developer'],
])
$employees->duplicates('position');
// [2 => 'Developer']
duplicatesStrict()
{#collection-method}
Метод использует ту же сигнатуру, что и duplicates
, но использует строгие сравнения.
each()
{#collection-method}
Метод each
перебирает элементы в коллекции и передает каждый элемент в функцию обратного вызова:
$collection->each(function ($item, $key) {
//
});
Верните false
из функции обратного вызова, чтобы выйти из цикла:
$collection->each(function ($item, $key) {
if (/* some condition */) {
return false;
}
});
eachSpread()
{#collection-method}
Метод eachSpread
метод производит итерацию по элементам коллекции, передавая каждое значение вложенного элемента в заданную функцию обратного вызова:
$collection = collect([['John Doe', 35], ['Jane Doe', 33]]);
$collection->eachSpread(function ($name, $age) {
//
});
Вы можете прекратить итерацию по элементам, возвращая false
из функции обратного вызова:
$collection->eachSpread(function ($name, $age) {
return false;
});
every()
{#collection-method}
Метод every
можно использовать, чтобы проверить, что все элементы коллекции прошли проверку на истинность:
collect([1, 2, 3, 4])->every(function ($value, $key) {
return $value > 2;
});
// false
Если коллекция пуста, every
вернёт true:
$collection = collect([]);
$collection->every(function ($value, $key) {
return $value > 2;
});
// true
except()
{#collection-method}
Метод except
возвращает все элементы в коллекции, кроме тех, чьи ключи указаны в передаваемом массиве:
$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]);
$filtered = $collection->except(['price', 'discount']);
$filtered->all();
// ['product_id' => 1]
Метод only - инверсный методу except
.
Поведение этого метода в коллекциях Eloquent изменено.
filter()
{#collection-method}
Метод filter
фильтрует коллекцию с помощью переданной функции обратного вызова, оставляя только те элементы, которые соответствуют заданному условию:
$collection = collect([1, 2, 3, 4]);
$filtered = $collection->filter(function ($value, $key) {
return $value > 2;
});
$filtered->all();
// [3, 4]
Если анонимная функция не указана, будут удалены все элементы коллекции, эквивалентные false
:
$collection = collect([1, 2, 3, null, false, '', 0, []]);
$collection->filter()->all();
// [1, 2, 3]
Метод reject - инверсный методу filter
.
first()
{#collection-method}
Метод first
возвращает первый элемент в коллекции, который подходит под заданное условие:
collect([1, 2, 3, 4])->first(function ($value, $key) {
return $value > 2;
});
// 3
Также вы можете вызвать метод first
без параметров, чтобы получить первый элемент в коллекции. Если коллекция пуста, то вернётся null
:
collect([1, 2, 3, 4])->first();
// 1
firstWhere()
{#collection-method}
Метод firstWhere
возвращает первый элемент в коллекции с заданной парой ключ-значение:
$collection = collect([
['name' => 'Regena', 'age' => null],
['name' => 'Linda', 'age' => 14],
['name' => 'Diego', 'age' => 23],
['name' => 'Linda', 'age' => 84],
]);
$collection->firstWhere('name', 'Linda');
// ['name' => 'Linda', 'age' => 14
Вы также можете вызвать метод firstWhere
с оператором:
$collection->firstWhere('age', '>=', 18);
// ['name' => 'Diego', 'age' => 23]
Как в методе where вы можете передать только один аргумент. В этом случае firstWhere
вернёт первый элемент, у которого найдётся данный ключ с непустым значением:
$collection->firstWhere('age');
// ['name' => 'Linda', 'age' => 14]
flatMap()
{#collection-method}
Метод flatMap
проходит по коллекции и передаёт каждое значение в заданную функцию обратного вызова. Эта функция может изменить элемент и вернуть его, формируя таким образом новую коллекцию модифицированных элементов. Затем массив "сплющивается" в одномерный:
$collection = collect([
['name' => 'Sally'],
['school' => 'Arkansas'],
['age' => 28]
]);
$flattened = $collection->flatMap(function ($values) {
return array_map('strtoupper', $values);
});
$flattened->all();
// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];
flatten()
{#collection-method}
Метод flatten
преобразует многомерную коллекцию в одномерную:
$collection = collect(['name' => 'taylor', 'languages' => ['php', 'javascript']]);
$flattened = $collection->flatten();
$flattened->all();
// ['taylor', 'php', 'javascript'];
При необходимости вы можете передать в метод аргумент "глубины":
$collection = collect([
'Apple' => [
['name' => 'iPhone 6S', 'brand' => 'Apple'],
],
'Samsung' => [
['name' => 'Galaxy S7', 'brand' => 'Samsung']
],
]);
$products = $collection->flatten(1);
$products->values()->all();
/*
[
['name' => 'iPhone 6S', 'brand' => 'Apple'],
['name' => 'Galaxy S7', 'brand' => 'Samsung'],
]
*/
В этом примере: если вызвать flatten
без указания глубины, то вложенные массивы тоже «расплющатся», и получим ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']
. Глубина задаёт уровень вложенности массивов, ниже которого "расплющивать" не нужно.
flip()
{#collection-method}
Метод flip
меняет местами ключи и значения в коллекции:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$flipped = $collection->flip();
$flipped->all();
// ['taylor' => 'name', 'laravel' => 'framework']
forget()
{#collection-method}
Метод forget
удаляет элемент из коллекции по его ключу:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$collection->forget('name');
$collection->all();
// ['framework' => 'laravel']
В отличие от большинства других методов коллекции,
forget
не возвращает новую модифицированную коллекцию. Он изменяет коллекцию при вызове.
forPage()
{#collection-method}
Метод forPage
возвращает новую коллекцию, содержащую элементы, которые будут присутствовать на странице с заданным номером. Первый аргумент метода — номер страницы, второй аргумент — число элементов для вывода на странице:
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunk = $collection->forPage(2, 3);
$chunk->all();
// [4, 5, 6]
get()
{#collection-method}
Метод get
возвращает нужный элемент по заданному ключу. Если ключ не существует, то возвращается null
:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('name');
// taylor
Вторым параметром вы можете передать значение по умолчанию:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']);
$value = $collection->get('foo', 'default-value');
// default-value
Вы даже можете передать функцию обратного вызова в качестве значения по умолчанию. Результат функции обратного вызова будет возвращён, если указанный ключ не существует:
$collection->get('email', function () {
return 'default-value';
});
// default-value
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->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()
{#collection-method}
Метод has
определяет, существует ли заданный ключ в коллекции:
$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]);
$collection->has('product');
// true
$collection->has(['product', 'amount']);
// true
$collection->has(['amount', 'price']);
// false
implode()
{#collection-method}
Метод implode
соединяет элементы в коллекции. Его параметры зависят от типа элементов в коллекции. Если коллекция содержит массивы или объекты, вы должны передать ключ атрибутов, значения которых вы хотите соединить, и "промежуточную" строку, которую вы хотите поместить между значениями:
$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'
intersect()
{#collection-method}
Метод intersect
удаляет любые значения из исходной коллекции, которых нет в переданном array
или коллекции. Результирующая коллекция сохранит ключи оригинальной коллекции:
$collection = collect(['Desk', 'Sofa', 'Chair']);
$intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']);
$intersect->all();
// [0 => 'Desk', 2 => 'Chair']
Поведение этого метода в коллекциях Eloquent изменено.
intersectByKeys()
{#collection-method}
Метод intersectByKeys
удаляет любые ключи из исходной коллекции, которых нет в переданном array
или коллекции:
$collection = collect([
'serial' => 'UX301', 'type' => 'screen', 'year' => 2009
]);
$intersect = $collection->intersectByKeys([
'reference' => 'UX404', 'type' => 'tab', 'year' => 2011
]);
$intersect->all();
// ['type' => 'screen', 'year' => 2009]
isEmpty()
{#collection-method}
Метод isEmpty
возвращает true
, если коллекция пуста. В противном случае вернётся false
:
collect([])->isEmpty();
// true
isNotEmpty()
{#collection-method}
Метод isNotEmpty
возвращает true
, если коллекция не пуста; в противном случае вернётся false
:
collect([])->isNotEmpty();
// false
join()
{#collection-method}
Метод join
объединяет элементы коллекции в строку с использованием указанного разделителя:
collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''
keyBy()
{#collection-method}
Метод keyBy
возвращает коллекцию по указанному ключу. Если несколько элементов имеют одинаковый ключ, в результирующей коллекции появится только последний их них:
$collection = collect([
['product_id' => 'prod-100', 'name' => 'Desk'],
['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$keyed = $collection->keyBy('product_id');
$keyed->all();
/*
[
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/
Также вы можете передать в метод функцию обратного вызова, которая должна возвращать значение ключа коллекции для этого метода:
$keyed = $collection->keyBy(function ($item) {
return strtoupper($item['product_id']);
});
$keyed->all();
/*
[
'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]
*/
keys()
{#collection-method}
Метод keys
возвращает все ключи коллекции:
$collection = collect([
'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'],
'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],
]);
$keys = $collection->keys();
$keys->all();
// ['prod-100', 'prod-200']
last()
{#collection-method}
Метод last
возвращает последний элемент в коллекции, который проходит проверку на истинность:
collect([1, 2, 3, 4])->last(function ($value, $key) {
return $value < 3;
});
// 2
Также вы можете вызвать метод last
без параметров, чтобы получить последний элемент в коллекции. Если коллекция пуста, то вернётся null
:
collect([1, 2, 3, 4])->last();
// 4
macro()
{#collection-method}
Статический метод macro
позволяет во время выполнения добавлять методы в класс Collection
. Для получения дополнительной информации смотрите документацию по расширению коллекций.
make()
{#collection-method}
Статический метод make
создает новый экземпляр коллекции. Смотрите раздел Создание коллекций.
map()
{#collection-method}
Метод map
перебирает коллекцию и передаёт каждое значению в функцию обратного вызова. Функция обратного вызова может свободно изменять элемент и возвращать его, формируя тем самым новую коллекцию измененных элементов:
$collection = collect([1, 2, 3, 4, 5]);
$multiplied = $collection->map(function ($item, $key) {
return $item * 2;
});
$multiplied->all();
// [2, 4, 6, 8, 10]
Как и большинство других методов коллекции, метод
map
возвращает новый экземпляр коллекции. Он не изменяет коллекцию при вызове. Если вы хотите преобразовать оригинальную коллекцию, используйте методtransform
.
mapInto()
{#collection-method}
Метод mapInto()
производит итерацию по коллекции, создавая новый экземпляр данного класса, передавая значение в конструктор:
class Currency
{
/**
* Create a new currency instance.
*
* @param string $code
* @return void
*/
function __construct(string $code)
{
$this->code = $code;
}
}
$collection = collect(['USD', 'EUR', 'GBP']);
$currencies = $collection->mapInto(Currency::class);
$currencies->all();
// [Currency('USD'), Currency('EUR'), Currency('GBP')]
mapSpread()
{#collection-method}
Метод mapSpread
производит итерацию по элементам коллекции, передавая каждое значение вложенного элемента в заданную функцию обратного вызова. Функция обратного вызова может свободно изменять элемент и возвращать его, формируя таким образом новую коллекцию измененных элементов:
$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
$chunks = $collection->chunk(2);
$sequence = $chunks->mapSpread(function ($even, $odd) {
return $even + $odd;
});
$sequence->all();
// [1, 5, 9, 13, 17]
mapToGroups()
{#collection-method}
Метод mapToGroups
группирует элементы коллекции по заданной функции обратного вызова. Функция обратного вызова должна возвращать ассоциативный массив, содержащий одну пару ключ-значение, формируя таким образом новый набор сгруппированных значений:
$collection = collect([
[
'name' => 'John Doe',
'department' => 'Sales',
],
[
'name' => 'Jane Doe',
'department' => 'Sales',
],
[
'name' => 'Johnny Doe',
'department' => 'Marketing',
]
]);
$grouped = $collection->mapToGroups(function ($item, $key) {
return [$item['department'] => $item['name']];
});
$grouped->toArray();
/*
[
'Sales' => ['John Doe', 'Jane Doe'],
'Marketing' => ['Johnny Doe'],
]
*/
$grouped->get('Sales')->all();
// ['John Doe', 'Jane Doe']
mapWithKeys()
{#collection-method}
Метод mapWithKeys
проходит по элементам коллекции и передаёт каждое значение в функцию обратного вызова, которая должна вернуть ассоциативный массив, содержащий одну пару ключ/значение:
$collection = collect([
[
'name' => 'John',
'department' => 'Sales',
'email' => 'john@example.com'
],
[
'name' => 'Jane',
'department' => 'Marketing',
'email' => 'jane@example.com'
]
]);
$keyed = $collection->mapWithKeys(function ($item) {
return [$item['email'] => $item['name']];
});
$keyed->all();
/*
[
'john@example.com' => 'John',
'jane@example.com' => 'Jane',
]
*/
max()
{#collection-method}
Метод max
возвращает максимальное значение по заданному ключу:
$max = collect([['foo' => 10], ['foo' => 20]])->max('foo');
// 20
$max = collect([1, 2, 3, 4, 5])->max();
// 5
median()
{#collection-method}
Метод median
возвращает медианное значение заданного ключа:
$median = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->median('foo');
// 15
$median = collect([1, 1, 2, 4])->median();
// 1.5
merge()
{#collection-method}
Метод merge
добавляет указанный массив в исходную коллекцию. Значения исходной коллекции, имеющие тот же строковый ключ, что и значение в массиве, будут перезаписаны:
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->merge(['price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => 1, 'price' => 200, 'discount' => false]
Если заданные ключи в массиве числовые, то значения будут добавляться в конец коллекции:
$collection = collect(['Desk', 'Chair']);
$merged = $collection->merge(['Bookcase', 'Door']);
$merged->all();
// ['Desk', 'Chair', 'Bookcase', 'Door']
mergeRecursive()
{#collection-method}
Метод mergeRecursive
рекурсивно объединяет данный массив или коллекцию с исходной коллекцией. Если строковый ключ совпадает со строковым ключом в исходной коллекции, то значения этих ключей объединяются в массив, и это делается рекурсивно:
$collection = collect(['product_id' => 1, 'price' => 100]);
$merged = $collection->mergeRecursive(['product_id' => 2, 'price' => 200, 'discount' => false]);
$merged->all();
// ['product_id' => [1, 2], 'price' => [100, 200], 'discount' => false]
min()
{#collection-method}
Метод min
возвращает минимальное значение по заданному ключу:
$min = collect([['foo' => 10], ['foo' => 20]])->min('foo');
// 10
$min = collect([1, 2, 3, 4, 5])->min();
// 1
mode()
{#collection-method}
Метод mode
возвращает значение мода заданного ключа:
$mode = collect([['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->mode('foo');
// [10]
$mode = collect([1, 1, 2, 4])->mode();
// [1]
nth()
{#collection-method}
Метод nth
создает новую коллекцию, состоящую из каждого n-ного элемента:
$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']);
$collection->nth(4);
// ['a', 'e']
Можно передать смещение в качестве необязательного второго аргумента:
$collection->nth(4, 1);
// ['b', 'f']
only()
{#collection-method}
Метод only
возвращает элементы коллекции с заданными ключами:
$collection = collect(['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]);
$filtered = $collection->only(['product_id', 'name']);
$filtered->all();
// ['product_id' => 1, 'name' => 'Desk']
Метод except - инверсный для метода only
.
Поведение этого метода в коллекциях Eloquent изменено.
pad()
{#collection-method}
Метод 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()
{#collection-method}
Метод partition
можно объединить с функцией PHP list
, чтобы отделить элементы, которые прошли заданную проверку на истинность от тех элементов, которые её не прошли:
$collection = collect([1, 2, 3, 4, 5, 6]);
list($underThree, $equalOrAboveThree) = $collection->partition(function ($i) {
return $i < 3;
});
$underThree->all();
// [1, 2]
$equalOrAboveThree->all();
// [3, 4, 5, 6]
pipe()
{#collection-method}
Метод pipe
передает коллекцию в заданную функцию и возвращает результат:
$collection = collect([1, 2, 3]);
$piped = $collection->pipe(function ($collection) {
return $collection->sum();
});
// 6
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']
Также вы можете указать, с каким ключом вы хотите получить коллекцию:
$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()
{#collection-method}
Метод pop
удаляет и возвращает последний элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$collection->pop();
// 5
$collection->all();
// [1, 2, 3, 4]
prepend()
{#collection-method}
Метод prepend
добавляет элемент в начало коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$collection->prepend(0);
$collection->all();
// [0, 1, 2, 3, 4, 5]
Вторым аргументом вы можете передать ключ добавляемого элемента:
$collection = collect(['one' => 1, 'two' => 2]);
$collection->prepend(0, 'zero');
$collection->all();
// ['zero' => 0, 'one' => 1, 'two' => 2]
pull()
{#collection-method}
Метод pull
удаляет и возвращает элемент из коллекции по его ключу:
$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']);
$collection->pull('name');
// 'Desk'
$collection->all();
// ['product_id' => 'prod-100']
push()
{#collection-method}
Метод push
добавляет элемент в конец коллекции:
$collection = collect([1, 2, 3, 4]);
$collection->push(5);
$collection->all();
// [1, 2, 3, 4, 5]
put()
{#collection-method}
Метод put
устанавливает заданный ключ и значение в коллекцию:
$collection = collect(['product_id' => 1, 'name' => 'Desk']);
$collection->put('price', 100);
$collection->all();
// ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
random()
{#collection-method}
Метод random
возвращает случайный элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$collection->random();
// 4 - (получен в случайном порядке)
Также вы можете передать целое число в random
, чтобы указать, сколько случайных элементов необходимо получить. Всегда возвращается коллекция элементов при явной передаче количества элементов, которые вам необходимо получить:
$random = $collection->random(3);
$random->all();
// [2, 4, 5] - (получены в случайном порядке)
Если в коллекции меньше значений, чем запрашивается, будет брошено исключение InvalidArgumentException
.
reduce()
{#collection-method}
Метод reduce
уменьшает коллекцию до одного значения, передавая результат каждой итерации в последующую итерацию:
$collection = collect([1, 2, 3]);
$total = $collection->reduce(function ($carry, $item) {
return $carry + $item;
});
// 6
Значение для $carry
в первой итерации — null
; однако, вы можете указать его начальное значение во втором параметре метода reduce
:
$collection->reduce(function ($carry, $item) {
return $carry + $item;
}, 4);
// 10
reject()
{#collection-method}
Метод reject
фильтрует коллекцию, используя заданную функцию обратного вызова. Функция обратного вызова должна возвращать true
для элементов, которые необходимо удалить из результирующей коллекции:
$collection = collect([1, 2, 3, 4]);
$filtered = $collection->reject(function ($value, $key) {
return $value > 2;
});
$filtered->all();
// [1, 2]
Метод filter
- инверсный для метода reject
.
replace()
{#collection-method}
Метод replace
ведет себя аналогично merge
, однако, в дополнение к перезаписи совпадающих элементов со строковыми ключами, метод replace
также перезапишет элементы в коллекции, которые имеют совпадающие числовые ключи:
$collection = collect(['Taylor', 'Abigail', 'James']);
$replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']);
$replaced->all();
// ['Taylor', 'Victoria', 'James', 'Finn']
replaceRecursive()
{#collection-method}
Этот метод работает как replace
, но он рекурсивно повторяется в подмассивах и применяет тот же процесс замены к внутренним значениям:
$collection = collect(['Taylor', 'Abigail', ['James', 'Victoria', 'Finn']]);
$replaced = $collection->replaceRecursive(['Charlie', 2 => [1 => 'King']]);
$replaced->all();
// ['Charlie', 'Abigail', ['James', 'King', 'Finn']]
reverse()
{#collection-method}
Метод reverse
меняет порядок элементов коллекции, сохраняя исходные ключи:
$collection = collect(['a', 'b', 'c', 'd', 'e']);
$reversed = $collection->reverse();
$reversed->all();
/*
[
4 => 'e',
3 => 'd',
2 => 'c',
1 => 'b',
0 => 'a',
]
*/
search()
{#collection-method}
Метод search
ищет в коллекции заданное значение и возвращает его ключ при успешном поиске. Если элемент не найден, то возвращается false
.
$collection = collect([2, 4, 6, 8]);
$collection->search(4);
// 1
Поиск проводится с помощью "неточного" сравнения, то есть строка с числовым значением будет считаться равной числу с таким же значением. Чтобы использовать строгое сравнение, передайте true
вторым параметром метода:
$collection->search('4', true);
// false
В качестве альтернативы, вы можете передать свою собственную функцию обратного вызова для поиска первого элемента, для которого выполняется ваше условие:
$collection->search(function ($item, $key) {
return $item > 5;
});
// 2
shift()
{#collection-method}
Метод shift
удаляет и возвращает первый элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$collection->shift();
// 1
$collection->all();
// [2, 3, 4, 5]
shuffle()
{#collection-method}
Метод shuffle
перемешивает элементы в коллекции случайным образом::
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
skip()
{#collection-method}
Метод skip
вернёт коллекцию без N первых элементов.
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$collection = $collection->skip(4);
$collection->all();
// [5, 6, 7, 8, 9, 10]
slice()
{#collection-method}
Метод slice
возвращает часть коллекции, начиная с заданного индекса:
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$slice = $collection->slice(4);
$slice->all();
// [5, 6, 7, 8, 9, 10]
Если вы хотите ограничить размер получаемой части коллекции, передайте желаемый размер вторым параметром в метод:
$slice = $collection->slice(4, 2);
$slice->all();
// [5, 6]
Полученная часть коллекции сохранит оригинальные ключи. Если вы не хотите сохранять оригинальные ключи, то можете использовать метод values
, чтобы переиндексировать их.
some()
{#collection-method}
Это псевдоним (алиас) для метода contains
.
sort()
{#collection-method}
Метод sort
сортирует коллекцию. Отсортированная коллекция сохраняет оригинальные ключи массива, поэтому в этом примере мы используем метод values
для сброса ключей и последовательной нумерации индексов:
$collection = collect([5, 3, 1, 2, 4]);
$sorted = $collection->sort();
$sorted->values()->all();
// [1, 2, 3, 4, 5]
Если вам необходимо отсортировать коллекцию с дополнительными условиями, вы можете передать функцию обратного вызова в метод sort
с вашим собственным алгоритмом. См. PHP документацию по uasort
, который вызывается внутри метода sort
вашей коллекции.
Для сортировки коллекции вложенных массивов или объектов, смотрите методы
sortBy
иsortByDesc
methods.
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],
]
*/
Также вы можете передать свою собственную анонимную функцию, чтобы определить как сортировать значения коллекции:
$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()
{#collection-method}
Этот метод использует такую же сигнатуру, как и метод sortBy
, но будет сортировать коллекцию в обратном порядке.
sortKeys()
{#collection-method}
Метод sortKeys
сортирует коллекцию по ключам исходного ассоциативного массива:
$collection = collect([
'id' => 22345,
'first' => 'John',
'last' => 'Doe',
]);
$sorted = $collection->sortKeys();
$sorted->all();
/*
[
'first' => 'John',
'id' => 22345,
'last' => 'Doe',
]
*/
sortKeysDesc()
{#collection-method}
Этот метод использует такую же сигнатуру, как и метод sortKeys
, но будет сортировать коллекцию в обратном порядке.
splice()
{#collection-method}
Метод splice
удаляет и возвращает часть элементов, начиная с заданного индекса:
$collection = collect([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2);
$chunk->all();
// [3, 4, 5]
$collection->all();
// [1, 2]
Вы можете передать второй параметр в метод для ограничения размера возвращаемой части коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2, 1);
$chunk->all();
// [3]
$collection->all();
// [1, 2, 4, 5]
Также вы можете передать в метод третий параметр, содержащий новые элементы, чтобы заменить элементы, которые будут удалены из коллекции:
$collection = collect([1, 2, 3, 4, 5]);
$chunk = $collection->splice(2, 1, [10, 11]);
$chunk->all();
// [3]
$collection->all();
// [1, 2, 10, 11, 4, 5]
split()
{#collection-method}
Метод split
разбивает коллекцию на заданное число групп:
$collection = collect([1, 2, 3, 4, 5]);
$groups = $collection->split(3);
$groups->toArray();
// [[1, 2], [3, 4], [5]]
sum()
{#collection-method}
Метод sum
возвращает сумму всех элементов в коллекции:
collect([1, 2, 3, 4, 5])->sum();
// 15
Если коллекция содержит вложенные массивы или объекты, вам нужно передать ключ для определения значений, которые нужно суммировать:
$collection = collect([
['name' => 'JavaScript: The Good Parts', 'pages' => 176],
['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],
]);
$collection->sum('pages');
// 1272
Также вы можете передать свою собственную функцию обратного вызова, чтобы определить, какие значения коллекции суммировать:
$collection = collect([
['name' => 'Chair', 'colors' => ['Black']],
['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
]);
$collection->sum(function ($product) {
return count($product['colors']);
});
// 6
take()
{#collection-method}
Метод take
возвращает новую коллекцию с заданным числом элементов:
$collection = collect([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(3);
$chunk->all();
// [0, 1, 2]
Также вы можете передать отрицательное целое число, чтобы получить определенное количество элементов с конца коллекции:
$collection = collect([0, 1, 2, 3, 4, 5]);
$chunk = $collection->take(-2);
$chunk->all();
// [4, 5]
tap()
{#collection-method}
Метод tap
передает коллекцию заданной анонимной функции, что позволяет "подключиться" к коллекции в определенный момент и сделать что-либо с элементами, не оказывая влияния на саму коллекцию:
collect([2, 4, 3, 1, 5])
->sort()
->tap(function ($collection) {
Log::debug('Values after sorting', $collection->values()->toArray());
})
->shift();
// 1
times()
{#collection-method}
Статический метод times
создает новую коллекцию, вызывая функцию заданное количество раз:
$collection = Collection::times(10, function ($number) {
return $number * 9;
});
$collection->all();
// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
Этот метод может быть полезен при комбинировании с фабрикой классов для создания моделей Eloquent:
$categories = Collection::times(3, function ($number) {
return factory(Category::class)->create(['name' => "Category No. $number"]);
});
$categories->all();
/*
[
['id' => 1, 'name' => 'Category No. 1'],
['id' => 2, 'name' => 'Category No. 2'],
['id' => 3, 'name' => 'Category No. 3'],
]
*/
toArray()
{#collection-method}
Метод toArray
преобразует коллекцию в простой массив. Если значения коллекции являются моделями Eloquent, то модели также будут преобразованы в массивы:
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toArray();
/*
[
['name' => 'Desk', 'price' => 200],
]
*/
Метод
toArray
также преобразует все вложенные объекты коллекции, являющиеся экземплярамиArrayable
, в массив. Если вы хотите получить исходный массив, используйте вместо этого методall
.
toJson()
{#collection-method}
Метод toJson
преобразует коллекцию в упорядоченную строку JSON:
$collection = collect(['name' => 'Desk', 'price' => 200]);
$collection->toJson();
// '{"name":"Desk", "price":200}'
transform()
{#collection-method}
Метод transform
перебирает коллекцию и вызывает заданную функцию обратного вызова для каждого элемента коллекции. Элементы коллекции будут заменены на значения, полученные из функции обратного вызова:
$collection = collect([1, 2, 3, 4, 5]);
$collection->transform(function ($item, $key) {
return $item * 2;
});
$collection->all();
// [2, 4, 6, 8, 10]
В отличие от большинства других методов коллекции, transform() изменяет саму коллекцию. Если вместо этого вы хотите создать новую коллекцию, используйте метод
map
.
union()
{#collection-method}
Метод union
добавляет данный массив в коллекцию. Если массив содержит ключи, которые уже есть в исходной коллекции, то будут оставлены значения исходной коллекции:
$collection = collect([1 => ['a'], 2 => ['b']]);
$union = $collection->union([3 => ['c'], 1 => ['b']]);
$union->all();
// [1 => ['a'], 2 => ['b'], 3 => ['c']]
unique()
{#collection-method}
Метод unique
возвращает все уникальные элементы в коллекции. Полученная коллекция сохраняет оригинальные ключи массива, поэтому в этом примере мы используем метод values
для сброса ключей последовательной нумерации индексов:
$collection = collect([1, 1, 2, 2, 3, 4, 2]);
$unique = $collection->unique();
$unique->values()->all();
// [1, 2, 3, 4]
Имея дело со вложенными массивами или объектами, вы можете задать ключ, используемый для определения уникальности:
$collection = collect([
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]);
$unique = $collection->unique('brand');
$unique->values()->all();
/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
]
*/
Также вы можете передать свою собственную анонимную функцию, чтобы определять уникальность элементов:
$unique = $collection->unique(function ($item) {
return $item['brand'].$item['type'];
});
$unique->values()->all();
/*
[
['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'],
['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'],
['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'],
['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],
]
*/
Метод unique
использует "неточные" сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу с тем же значением. Используйте метод uniqueStrict
для фильтрации с использованием строгих сравнений.
Поведение этого метода в коллекциях Eloquent изменено.
uniqueStrict()
{#collection-method}
У этого метода та же сигнатура, как и у метода unique
; однако, все значения сравниваются путем "строгих" сравнений.
unless()
{#collection-method}
Метод unless
будет выполнять заданную функцию обратного вызова до тех пор, пока первый аргумент, переданный методу, не станет равен true
:
$collection = collect([1, 2, 3]);
$collection->unless(true, function ($collection) {
return $collection->push(4);
});
$collection->unless(false, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 5]
В качестве противоположности методу unless
, смотрите метод when
.
unlessEmpty()
{#collection-method}
Псевдоним (алиас) метода whenNotEmpty
.
unlessNotEmpty()
{#collection-method}
Псевдоним (алиас0) метода whenEmpty
.
unwrap()
{#collection-method}
Статический метод unwrap
возвращает исходные элементы коллекции из заданного значения, когда это применимо:
Collection::unwrap(collect('John Doe'));
// ['John Doe']
Collection::unwrap(['John Doe']);
// ['John Doe']
Collection::unwrap('John Doe');
// 'John Doe'
values()
{#collection-method}
Метод values
возвращает новую коллекцию со сброшенными ключами и последовательно пронумерованными индексами:
$collection = collect([
10 => ['product' => 'Desk', 'price' => 200],
11 => ['product' => 'Desk', 'price' => 200]
]);
$values = $collection->values();
$values->all();
/*
[
0 => ['product' => 'Desk', 'price' => 200],
1 => ['product' => 'Desk', 'price' => 200],
]
*/
when()
{#collection-method}
Метод when
выполнит заданную анонимную функцию, когда первый переданный методу элемент будет равен true
:
$collection = collect([1, 2, 3]);
$collection->when(true, function ($collection) {
return $collection->push(4);
});
$collection->when(false, function ($collection) {
return $collection->push(5);
});
$collection->all();
// [1, 2, 3, 4]
В качестве протиповоложности методу when
, смотрите метод unless
.
whenEmpty()
{#collection-method}
Метод whenEmpty
выполняет заданную в аргументах функцию, если коллекция пуста:
$collection = collect(['michael', 'tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['michael', 'tom']
$collection = collect();
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['adam']
$collection = collect(['michael', 'tom']);
$collection->whenEmpty(function ($collection) {
return $collection->push('adam');
}, function ($collection) {
return $collection->push('taylor');
});
$collection->all();
// ['michael', 'tom', 'taylor']
В качестве протиповоложности методу whenEmpty
смотрите метод whenNotEmpty
.
whenNotEmpty()
{#collection-method}
Метод whenNotEmpty
выполняет данную в аргументах функцию, если коллекция не пуста:
$collection = collect(['michael', 'tom']);
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// ['michael', 'tom', 'adam']
$collection = collect();
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
});
$collection->all();
// []
$collection = collect();
$collection->whenNotEmpty(function ($collection) {
return $collection->push('adam');
}, function ($collection) {
return $collection->push('taylor');
});
$collection->all();
// ['taylor']
В качестве протиповоложности методу whenNotEmpty
смотрите метод whenEmpty
.
where()
{#collection-method}
Метод where
фильтрует коллекцию по заданной паре ключ/значение:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->where('price', 100);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/
Метод where
использует "неточные" сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу с тем же значением. Используйте метод whereStrict
для фильтрации с использованием строгих сравнений.
Опционально вы можете передать оператор сравнения вторым параметром:
$collection = collect([
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
['name' => 'Sue', 'deleted_at' => null],
]);
$filtered = $collection->where('deleted_at', '!=', null);
$filtered->all();
/*
[
['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
]
*/
whereStrict()
{#collection-method}
Этот метод имеет такую же сигнатуру, как и метод where
; однако, все значения сравниваются с использованием строгого сравнения.
whereBetween()
{#collection-method}
Метод whereBetween
возвращает элементы коллекции, значения которых по заданному ключу попадают в заданный диапазон:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereBetween('price', [100, 200]);
$filtered->all();
/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]
*/
whereIn()
{#collection-method}
Метод whereIn
фильтрует коллекцию по заданным ключу/значению, содержащимся в данном массиве:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereIn('price', [150, 200]);
$filtered->all();
/*
[
['product' => 'Desk', 'price' => 200],
['product' => 'Bookcase', 'price' => 150],
]
*/
Метод whereIn
использует "неточные" сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу с тем же значением. Используйте метод whereInStrict
для фильтрации с использованием строгих сравнений.
whereInStrict()
{#collection-method}
Этот метод имеет такую же сигнатуру, как и метод whereIn
; однако, все значения сравниваются с использованием строгого сравнения.
whereInstanceOf()
{#collection-method}
The whereInstanceOf
фильтрует коллекцию по принадлежности элемента некому классу:
use App\User;
use App\Post;
$collection = collect([
new User,
new User,
new Post,
]);
$filtered = $collection->whereInstanceOf(User::class);
$filtered->all();
// [App\User, App\User]
whereNotBetween()
{#collection-method}
Метод whereNotBetween
возвращает элементы коллекции, значения которых по заданному ключу НЕ попадают в заданный диапазон:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 80],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Pencil', 'price' => 30],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereNotBetween('price', [100, 200]);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 80],
['product' => 'Pencil', 'price' => 30],
]
*/
whereNotIn()
{#collection-method}
Метод whereNotIn
фильтрует коллекцию по заданным ключу/значению, которые не содержатся в данном массиве:
$collection = collect([
['product' => 'Desk', 'price' => 200],
['product' => 'Chair', 'price' => 100],
['product' => 'Bookcase', 'price' => 150],
['product' => 'Door', 'price' => 100],
]);
$filtered = $collection->whereNotIn('price', [150, 200]);
$filtered->all();
/*
[
['product' => 'Chair', 'price' => 100],
['product' => 'Door', 'price' => 100],
]
*/
Метод whereNotIn
использует "неточные" сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу с тем же значением. Используйте метод whereNotInStrict
для фильтрации с использованием строгих сравнений.
whereNotInStrict()
{#collection-method}
Этот метод имеет такую же сигнатуру, как и метод whereNotIn
; однако, все значения сравниваются с использованием строгого сравнения.
whereNotNull()
{#collection-method}
Метод whereNotNull
фильтрует элементы коллекции, у которых значение переданного ключа НЕ является null.
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNotNull('name');
$filtered->all();
/*
[
['name' => 'Desk'],
['name' => 'Bookcase'],
]
*/
whereNull()
{#collection-method}
Метод whereNotNull
фильтрует элементы коллекции, у которых значение переданного ключа является null.
$collection = collect([
['name' => 'Desk'],
['name' => null],
['name' => 'Bookcase'],
]);
$filtered = $collection->whereNull('name');
$filtered->all();
/*
[
['name' => null],
]
*/
wrap()
{#collection-method}
Статический метод 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()
{#collection-method}
Метод zip
объединяет все значения заданного массива со значениями исходной коллекции на соответствующем индексе:
$collection = collect(['Chair', 'Desk']);
$zipped = $collection->zip([100, 200]);
$zipped->all();
// [['Chair', 100], ['Desk', 200]]
Операции высшего порядка
Коллекции также поддерживают операции высшего порядка, которые служат сокращениями для выполнения обычных действий с коллекциями. Методы коллекций, которые предоставляют операции высшего порядка: average
, avg
, contains
, each
, every
, filter
, first
, flatMap
, groupBy
, keyBy
, map
, max
, min
, partition
, reject
, some
, sortBy
, sortByDesc
, sum
, unique
.
Доступ к каждой операции высшего порядка можно получить как к динамическому свойству экземпляра коллекции. К примеру, давайте используем операцию each
, чтобы вызывать метод для каждого объекта в коллекции:
$users = User::where('votes', '>', 500)->get();
$users->each->markAsVip();
Таким же образом, мы можем использовать операцию sum
, чтобы получить общее количество "голосов" пользователей коллекции:
$users = User::where('group', 'Development')->get();
return $users->sum->votes;
Ленивые коллекции
Введение
Если вы не знакомы с PHP-генераторами - самое время это сделать.
To supplement the already powerful Collection
class, the LazyCollection
class leverages PHP's generators to allow you to work with very large datasets while keeping memory usage low.
Класс LazyCollection
использует в своей работе генераторы PHP, что полезно при больших объемах данных, так как позволяет драматически сократить использование памяти.
For example, imagine your application needs to process a multi-gigabyte log file while taking advantage of Laravel's collection methods to parse the logs. Instead of reading the entire file into memory at once, lazy collections may be used to keep only a small part of the file in memory at a given time:
Для примера, возмём случай парсинга многогигабайтного тектового лога. Вместо того, чтобы целиком читать его в коллекцию, при помощи ленивых коллекций его можно обрабатывать мелкими частями:
use App\LogEntry;
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
})->chunk(4)->map(function ($lines) {
return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
// Process the log entry...
});
Or, imagine you need to iterate through 10,000 Eloquent models. When using traditional Laravel collections, all 10,000 Eloquent models must be loaded into memory at the same time:
Или, например, возьмём случай, когда надо обработать результат из 10000 элоквент-моделей. При традиционном подходе все эти модели придётся загрузить в память сразу:
$users = App\User::all()->filter(function ($user) {
return $user->id > 500;
});
However, the query builder's cursor
method returns a LazyCollection
instance. This allows you to still only run a single query against the database but also only keep one Eloquent model loaded in memory at a time. In this example, the filter
callback is not executed until we actually iterate over each user individually, allowing for a drastic reduction in memory usage:
Однако можно воспользоваться методом cursor()
, который возвращает экземпляр LazyCollection
. Это позволит нам по-прежнему выполнять только один запрос к базе данных, но одновременно сохранять в памяти только одну модель Eloquent. В этом примере filter
не выполняется до тех пор, пока мы фактически не проведем итерацию по каждому пользователю индивидуально, что позволит значительно сократить использование памяти:
$users = App\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}
Создание ленивых коллекций
Ленивые коллекции могут быть созданы при помощи метода make
:
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
});
Контракт Enumerable
Almost all methods available on the Collection
class are also available on the LazyCollection
class. Both of these classes implement the Illuminate\Support\Enumerable
contract, which defines the following methods:
Почти все методы Collection
также доступны в LazyCollection
. Оба этих класса реализуют интерфейс Illuminate\Support\Enumerable
, в котором определены следующие методы:
all average avg chunk collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys dump duplicates duplicatesStrict each eachSpread every except filter first firstWhere flatMap flatten flip forPage get groupBy has implode intersect intersectByKeys isEmpty isNotEmpty join keyBy keys last macro make map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode nth only pad partition pipe pluck random reduce reject replace replaceRecursive reverse search shuffle skip slice some sort sortBy sortByDesc sortKeys sortKeysDesc split sum take tap times toArray toJson union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict wrap zip
Обратите внимание, что методы, изменяющие, мутирующие коллекцию (
shift
,pop
,prepend
и т.п.) отсуствуют вLazyCollection
.
Свои методы ленивых коллекций
В дополнение к методам интерфейса Enumerable
, у LazyCollection
есть свои уникальные методы:
tapEach()
{#collection-method}
В то время как метод each
сразу вызывает заданную в аргументах функцию для каждого элемента в коллекции, метод tapEach
вызывает её, только когда элементы вытягиваются из списка один за другим:
$lazyCollection = LazyCollection::times(INF)->tapEach(function ($value) {
dump($value);
});
// Nothing has been dumped so far...
$array = $lazyCollection->take(3)->all();
// 1
// 2
// 3
remember()
{#collection-method}
Метод remember
возвращает новую ленивую коллекцию, которая запомнит все значения, которые уже были перечислены, и не получит их снова при повторном перечислении коллекции:
$users = User::cursor()->remember();
// запросы в БД не делаются
$users->take(5)->all();
// Выполнится запрос и 5 первых пользователей будут взяты из БД
$users->take(20)->all();
// Первые 5 пользователей будут взяты из кэша, остальные - из БД