Коллекции в Laravel 7

Описание всех методов с примерами

Коллекция - объект, который представляет собой массив каких-то данных с готовыми инструментами для поиска, фильтрации и различного рода манипуляций над этими данными с помощью вызова методов цепным способом.

Определенно неплохая коллекция книг

По сути, это обычный массив [], который поставляется с готовыми инструментами для операций над этим массивом, что может в несколько раз уменьшить размер и упростить читаемость кода в местах, где идёт работа с массивами данных.

Коллекция является очень удобным инструментом, однако не каждый разработчик может с легкостью разобраться в его коде, если увидит его впервые. Я советую вам проверить на практике каждый метод, который будет рассмотрен на данной странице для более лучшего усвоения информации.

Создание коллекции

В Laravel, как правило, вы будете принимать готовую коллекцию (например, результат запроса в БД), а не создавать её.

Однако, создать коллекцию можно и самому, использовав функцию collect(). Можно вызывать эту функцию и без аргументов (тогда будет создана пустая коллекция), но также можно передать массив, который будет автоматически преобразован в коллекцию.

1 2 3 4 5 6 7 8 9 10 11
// Создать пустую коллекцию $collection = collect();   // Создать коллекцию с данными $data = [ 'name' => 'Роман', 'city' => 'Москва', 'profession' => 'PHP разработчик', ];   $collection = collect($data);

Методы коллекции

Как я говорил ранее, коллекция - объект, в котором можно вызывать методы цепным способом. Это значит, что после каждого выполнения метода он вернет коллекцию.

Таким образом, можно выполнить несколько сложных (с точки зрения обычной работы с массивами) операций в рамках одного обращения к коллекции. Это очень удобно и упрощает читаемость кода.

all()

Возвращает все элементы коллекции в виде массива.

$collection = collect([1, 2, 3]);
 
// Получим значения в виде массива
$collection->all(); 
 
// [1, 2, 3]

toArray()

Возвращает все элементы коллекции в виде массива. Отличается от all() тем, что toArray() также преобразит в массив все вложенные объекты-коллекции (например Eloquent модели).

1 2 3 4 5 6 7 8 9 10 11 12 13
$users = collect([ collect(['id' => 1, 'name' => 'Роман']), collect(['id' => 2, 'name' => 'Сергей']), ]);   $users->toArray();   /* [ ['id' => 1, 'name' => 'Роман'], ['id' => 2, 'name' => 'Сергей'], ] */

Давайте на этом же примере, сравним этот метод с методом all()

1 2 3 4 5 6 7 8 9 10 11 12
$users->all();   /* [ Collection { ['id' => 1, 'name' => 'Роман'] }, Collection { ['id' => 2, 'name' => 'Сергей'] }, ] */

avg(), average()

Возвращает среднее-арифметическое значение среди элементов коллекции. По факту, это один и тот же метод - average() является псевдонимом для метода avg().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
collect([1,3,8])->avg(); // 4 (потому что (1 + 3 + 8) / 3 = 4   /* * Еще один пример. */ $daysInMonthsCount = collect([ 'Январь' => 31, 'Февраль' => collect([28,29])->average(), // average() - то же, что и avg() 'Март' => 31, 'Апрель' => 30, 'Май' => 31, 'Июнь' => 30, 'Июль' => 31, 'Август' => 31, 'Сентябрь' => 30, 'Октябрь' => 31, 'Ноябрь' => 30, 'Декабрь' => 31, ]);   $daysInMonthsCount->avg();   // Среднее количество дней в месяце - 30.458333333333

chunk()

Разбивает коллекцию на множество мелких коллекций определенной длины.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$collection = collect([1, 2, 3, 4, 5, 6, 7]);   $chunks = $collection->chunk(4);   $chunks->toArray();   /* [ [1, 2, 3, 4], [ 4 => 5, 5 => 6, 6 => 7, ] ] */

Как нам подсказывает документация Laravel, этот метод - хороший способ для вывода сетки в вашем отображении (view) в связке с каким-нибудь фронтенд фреймворком, например Bootstrap:

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

Преобразует коллекцию массивов в единую коллекцию. Противоположность метода chunk().

$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 = collect(['name', 'surname']);
 
$combined = $collection->combine(['Роман', 'Сарваров']);
 
$combined->all();
 
// ['name' => 'Роман', 'surname' => 'Сарваров']

concat()

Добавляет вконец коллекции другую коллекцию или массив.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
$collected = collect(['Коллекция']) ->concat(['это']) ->concat(['очень']) ->concat(['просто']);   /* * Также может принимать коллекцию: * * $collected = * collect(['Коллекция']) * ->concat(collect(['это'])) * ->concat(collect(['очень'])) * ->concat(collect(['просто'])); */   $collected->toArray();   // ['Коллекция', 'это', 'очень', 'просто']

contains(), some()

Проверяет коллекцию на наличие значения (аналог функции in_array для PHP массивов).

$collection = collect(['name' => 'Роман']);
 
$collection->contains('Roman'); // false
$collection->contains('роман'); // false
$collection->contains('Роман'); // true

Также с помощью этого метода можно удостовериться в существовании какой-то пары, передав значение во второй аргумент. Более того, между ними можно добавить оператор сравнения.

1 2 3 4 5 6 7 8 9 10 11 12
$users = collect([ ['name' => 'Роман', 'age' => 23], ['name' => 'Денис', 'age' => 35], ['name' => 'Егор', 'age' => 14], ]);   $users->contains('name', 'Максим'); // false $users->contains('name', 'Роман'); // true   $users->contains('name', '!=', 'Максим'); // true $users->contains('age', '>', 30); // true $users->contains('age', '>=', 55); // false

Можно пойти дальше и в аргумент указать лишь callback-функцию, чтобы составлять свои условия. Продолжим предыдущий пример:

$users->contains(
    fn($value, $key) => $value['age'] >= 35
); // true
 
$users->contains(
    fn($value, $key) => $value['age'] > 55
); // false

Обратите внимание, что в этом методе используется нестрогое сравнение. Чтобы помимо значения сравнивался и тип данных, используйте метод containsStrict().

containsStrict()

По аналогии с contains() проверяет коллекцию на наличие какого-то значения, однако, по сравнению с ним, использует строгое сравнение (сравнивает еще и тип данных).

1 2 3 4 5 6 7 8 9 10 11
$collection = collect([ ['name' => 'Роман', 'age' => 23], ['name' => 'Денис', 'age' => 35], ['name' => 'Егор', 'age' => 14], ]);   $collection->contains('age', 23); // true $collection->contains('age', '23'); // true   $collection->containsStrict('age', 23); // true $collection->containsStrict('age','23'); // false

count()

Возвращает количество элементов в массиве.

$collection = collect([1, 1, 5, 4]);
 
$collection->count(); // 4

countBy()

Подсчитывает число вхождений значений в коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$collection = collect([ ['name' => 'Роман'], ['name' => 'Алексей'], ['name' => 'Сергей'], ['name' => 'Роман'], ]);   $counted = $collection->countBy();   $counted->all();   /* [ 'Роман' => 2, 'Алексей' => 1, 'Сергей' => 1, ] */

Также, можно передать callback-функцию, если нужно реализовать свою логику подсчета:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
$collection = collect([ ['name' => 'Роман', 'contact_info' => '+7 (999) 888-33-44'], ['name' => 'Алексей', 'contact_info' => '+7 (495) 123-12-21'], ['name' => 'Сергей', 'contact_info' => 'some.email@sarvarov.dev'], ['name' => 'Роман', 'contact_info' => 'one.more@email.com'], ['name' => 'Андрей', 'contact_info' => '+7 (925) 454-89-17'], ]);   // Посчитаем, сколько пользователей оставили свой Email в качестве контактной информации $countBy = $collection->countBy( fn($contactInfo) => strpos($contactInfo['contact_info'] ?? '', '@') !== false ? 'email' : 'phone' );   $countBy->all();   /* [ 'phone' => 3, 'email' => 2, ] */

crossJoin()

Возвращает все возможные перестановки коллекции с значениями переданного в аргументе массива. Простыми словами, возвращает значения "каждый с каждым".

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
$workers = collect(['Роман', 'Сергей', 'Алексей']);   $workersLife = $workers->crossJoin([ 'Встал с утра', 'Пошел на работу', 'Пришел с работы', 'Лёг спать' ]);   $workersLife->all(); /* [ ['Роман', 'Встал с утра'], ['Роман', 'Пошел на работу'], ['Роман', 'Пришел с работы'], ['Роман', 'Лёг спать'],   ['Сергей', 'Встал с утра'], ['Сергей', 'Пошел на работу'], ['Сергей', 'Пришел с работы'], ['Сергей', 'Лёг спать'],   ['Алексей', 'Встал с утра'], ['Алексей', 'Пошел на работу'], ['Алексей', 'Пришел с работы'], ['Алексей', 'Лёг спать'], ] */

diff()

Сравнивает коллекцию с другой коллекцией или обычным массивом [] и возвращает разницу - те элементы, которые отсутствуют в передаваемом массиве.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$students = collect([ 'Евгений', 'Лена', 'Максим', 'Игорь', 'Аня', 'Петр', ]);   // Проведем перекличку студентов и узнаем кто отсутствует на уроке $truants = $students->diff(['Игорь', 'Лена', 'Аня']);   $truants->all();   // ['Евгений', 'Максим', 'Петр']

diffAssoc()

Сравнивает ключи и значения элементов одной коллекции с ключами и значениями элементов другой коллекцией или обычного массива [] и возвращает разницу - те элементы, которые отсутствуют в передаваемом массиве.

Отличается от diff() тем, что помимо значений сравнивает ещё и ключи.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$collection = collect([ 'name' => 'яблоко', 'color' => 'красный', 'type' => 'фрукт', ]);   $diff = $collection->diffAssoc([ 'name' => 'яблоко', 'color' => 'зеленый', 'type' => 'фрукт', ]);   $diff->all();   // ['color' => 'красный']

diffKeys()

Сравнивает ключи элементов одной коллекции с ключами элементов другой коллекцией или обычного массива [] и возвращает разницу - ключи, которые отсутствуют в передаваемом массиве, а также их значения.

1 2 3 4 5 6 7 8 9 10 11 12
$collection = collect([ 'key_one' => 'Какое-то значение', 'key_two' => 'Этого элемента не будет в передаваемом массиве', ]);   $diff = $collection->diffKeys([ 'key_one' => 'Ещё какое-то значение!!!', ]);   $diff->all();   // ['key_two' => 'Этого элемента не будет в передаваемом массиве']

duplicates()

Возвращает повторяющиеся значения из коллекции. Используется нестрогое сравнение (не сравнивается тип, в отличие от duplicatesStrict()).

$collection = collect(['а', 'б', 'в', 'а', 'в']);
 
$dublicates = $collection->duplicates();
 
$dublicates->all()
 
// ['а', 'в']

Кроме того, можно в аргумент передать callback-функцию или же название ключа, по которому сравнивать элементы (в случае, если элементы коллекции - объекты/массивы).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$users = collect([ ['id' => 1, 'name' => 'Роман'], ['id' => 2, 'name' => 'Евгений'], ['id' => 3, 'name' => 'Максим'], ['id' => 4, 'name' => 'Роман'], ]);   $dublicateNames = $users->duplicates(fn($val) => $val['name']);   // Тоже самое, но проще: $dublicateNames = $users->duplicates('name');   $dublicateNames->all();   // ['Роман']

duplicatesStrict()

Возвращает повторяющиеся значения из коллекции. В отличие от duplicates() - помимо значения, сравнивает еще и тип данных.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
$collection = collect([ ['id' => 1], ['id' => '1'], ['id' => 'one'], ]);   /* ПРОВЕРКА dublicates() */   $dublicates = $collection->duplicates('id');   $dublicates->all(); // ['1']   /* ПРОВЕРКА duplicatesStrict() */   $dublicates = $collection->duplicatesStrict('id');   $dublicates->all(); // [] - вернуло пустой массив, так как (int)1 !== (string)'1'

every()

Проверяет все элементы коллекции по какому-то условию. Если все элементы прошли тест - вернет true, в противном случае false.

Если коллекция пустая - будет возвращать true в любом случае.

В качестве аргумента передается callback-функция, которая должна содержать какой-то тест и возвращать true или false. В случае, если элементы коллекции - массив, можно передать ключ, оператор и значение.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$users = collect([ ['id' => 1, 'name' => 'Роман', 'is_admin' => true], ['id' => 2, 'name' => 'Анна', 'is_admin' => true], ['id' => 3, 'name' => 'Борис', 'is_admin' => false], ]);   /* Проверим, являются ли все пользователи в коллекции администраторами */ /* Эти 3 строки являются идентичными: */   // $users->every(fn($value, $key) => $value['is_admin'] ?? false); // $users->every('is_admin', '=', true); $users->every('is_admin', true);   // false (Борис не администратор)

only()

Возвращает элементы коллекции с определенными ключами, которые были переданы в аргументе метода.

1 2 3 4 5 6 7 8 9 10 11
$users = collect([ 'id' => 1, 'name' => 'Роман', 'password' => '$2y$10$nsipFleZ3hQkrmhW3N40aOFMqT.swZyyb/TgZ1JUu3H1QRMhxZ3Wq', 'email' => 'roman@sarvarov.dev', ]);   $safeUsersDataCollection = $users->only('id', 'name');   $safeUsersDataCollection->all(); // ['id' => 1, 'name' => 'Роман']

Если нужно, наоборот, вернуть все элементы коллекции, кроме определенных - используйте except().

except()

Возвращает все элементы коллекции, за исключением тех, ключи которых переданы в функцию в виде массива. Противоположность метода only().

1 2 3 4 5 6 7 8 9 10 11
$users = collect([ 'id' => 1, 'name' => 'Роман', 'password' => '$2y$10$nsipFleZ3hQkrmhW3N40aOFMqT.swZyyb/TgZ1JUu3H1QRMhxZ3Wq', 'email' => 'roman@sarvarov.dev', ]);   $safeUsersDataCollection = $users->except('password', 'email');   $safeUsersDataCollection->all(); // ['id' => 1, 'name' => 'Роман']

unique(), uniqueStrict()

Возвращает уникальные значения элементов коллекции. Сохраняет ключи (если нужно их сбросить - примените к коллекции метод values()).

uniqueStrict() отличается от unique() тем, что производит строгое сравнение (помимо значения, сравнивает ещё и тип данных, а не делает приведение).

$collection = collect([1, 1, '1', 2, 'строка', 2, null, 4, 2, []]);
 
/* Нестрогое сравнение данных */
$collection->unique()->values()->all();
// [1, 2, 'строка', null, 4]
 
/* Строгое сравнение данных */
$collection->uniqueStrict()->values()->all();
// [1, '1', 2, 'строка', null, 4, []]

Можно передать строку с ключом, тогда будут возвращены все элементы с уникальными значениями по этому ключу.

Кроме того, можно передать callback-функцию со своей логикой определения уникальности элемента.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
$gadgets = collect([ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'телефон'], ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'телефон'], ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'часы'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'телефон'], ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'часы'], ]);   $gadgets->unique('brand')->values()->all(); /* [ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'телефон'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'телефон'], ] */   $gadgets->unique( fn($item, $key) => "{$item['brand']}_{$item['type']}" )->values()->all(); /* [ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'телефон'], ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'часы'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'телефон'], ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'часы'], ] */

filter()

Фильтрует и возвращает только те элементы коллекции, которые соответствуют заданному условию. Противоположность метода reject().

Условие определяется в переданной в аргументе callback-функцией. Если эта функция возвращает true - элемент остается в выборке, если false - то нет.

Если передать callback-функцию в виде аргумента, то из выборки пропадут все элементы, эквивалентные false.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$collection = collect([0, null, 1, 2, 3, 4, '', 5, 6, 7, 8, false, []]);   // Оставим только цифры, которые делятся на 2. Так же оставим все нечисловые значения для будущего теста. $filtered = $collection->filter( fn($value, $key) => (is_numeric($value) && $value % 2 === 0) || !is_numeric($value) );   $filtered->all(); // 0, null, 2, 4, '', 6, 8, false, []   $filtered = $filtered->filter();   $filtered->all(); // [2, 4, 6, 8]

reject()

Фильтрует и возвращает элементы коллекции с помощью callback-функции. Является противоположностью метода filter(): если callback-функция возвращает true - этот элемент НЕ попадет в финальную выборку.

1 2 3 4 5 6 7 8 9 10 11
$collection = collect([0, null, 1, 2, 3, 4, '', 5, 6, 7, 8, false, []]);   /* Удалим все элементы коллекции, которые являются true */ $rejected = $collection->reject(); $rejected->all(); // [0, null, '', false, []]   /* Удалим все нечисловые значения */ $rejected = $rejected->reject(fn($value, $key) => !is_numeric($value)); $rejected->all(); // [0]

get()

Возвращает элемент коллекции по переданному ключу. Если такого ключа не существует, вернет null или значение по умолчанию (которое можно передать во втором аргументе).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$user = collect([ 'id' => 1, 'name' => 'Роман', ]);   $user->get('name'); // Роман   $user->get('is_admin', false); /* * Вернет false (т.к. ключа is_admin не существует) * * Тоже самое что $user['is_admin'] ?? false * и $user->get('is_admin', fn() => false) */

pluck()

Извлекает все значения элементов по заданному ключу. Можно указать ещё одно название ключа (во втором аргументе), в таком случае ключи в новой коллекции будут установлены на значения ключей исходной коллекции, а также значения могут быть перезаписаны при дублировании.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$users = collect([ ['id' => 34, 'name' => 'Роман'], ['id' => 875, 'name' => 'Евгений'], ['id' => 166, 'name' => 'Максим'], ['id' => 819, 'name' => 'Роман'], ['id' => 34, 'name' => 'Петр'], ]);   $usersNames = $users->pluck('name'); $usersNames->all(); // ['Роман', 'Евгений', 'Максим', 'Роман'];   $users = $users->pluck('name', 'id'); $users->all(); // [34 => 'Петр', 875 => 'Евгений', 166 => 'Максим', 819 => 'Роман'];

Выполняет поиск по значениям элементов коллекции и возвращает ключ элемента, если значение было найдено, и false если значение не получилось найти. Поиск происходит до первого найденного элемента.

В процессе поиска идёт нестрогое сравнение (не сопоставляются типы данных переменных). Чтобы использовать строгое сравнение - передайте true во второй аргумент при вызове метода.

Кроме того, вместо строки с искомым значением, можно передать callback-функцию со своей логикой нахождения нужного элемента.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
$collection = collect([2, 6, 4, 4, '6', 8]);   $collection->search(4); // 2 (находит только первое значение и прекращает поиск)   $collection->search('6', true); // 4 (строгое сравнение типов)   $collection->search(9999); // false   $users = collect([ ['id' => 1, 'name' => 'Илья', 'age' => 35], ['id' => 2, 'name' => 'Роман', 'age' => 23], ['id' => 3, 'name' => 'Глеб', 'age' => 84], ['id' => 4, 'name' => 'Максим', 'age' => 14], ]);   /* Найдем Романа */ $users->search(fn($value, $key) => Str::startsWith( Str::lower($value['name']), 'рома') ); // 1

where(), whereStrict()

Фильтрует коллекцию с помощью переданной пары ключей/значений. В первый аргумент передается ключ, во второй - значение. Также, между ними можно добавить ещё один аргумент - оператор.

whereStrict() отличается от where() тем, что производит строгое сравнение (помимо значения, сравнивает ещё и тип данных, а не делает приведение).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
$users = collect([ ['id' => 1, 'name' => 'Илья', 'age' => 28], ['id' => 2, 'name' => 'Роман', 'age' => 23, 'is_admin' => true], ['id' => 3, 'name' => 'Максим', 'age' => 44], ['id' => 4, 'name' => 'Семён', 'age' => 29], ['id' => 5, 'name' => 'Василий', 'age' => 32, 'is_admin' => true], ['id' => 6, 'name' => 'Владимир', 'age' => 16], ['id' => 7, 'name' => 'Роман', 'age' => 58], ['id' => 8, 'name' => 'Максим', 'age' => 23], ]);   /* Простой поиск */ $admins = $users->where('is_admin', true); // Тоже самое что и $users->where('is_admin', 1); // Тоже самое что и $users->where('is_admin', '=', true);   $admins->all(); /* [ ['id' => 2, 'name' => 'Роман', 'age' => 23, 'is_admin' => true], ['id' => 5, 'name' => 'Василий', 'age' => 32, 'is_admin' => true], ] */   /* Строгое сравнение данных */ $admins = $users->whereStrict('is_admin', 1);   $admins->all(); // [] - ничего не нашло, так как (int)1 !== (bool)true   /* Поиск с оператором */ $oldGuys = $users->where('age', '>', 30);   $oldGuys->all(); /* [ ['id' => 3, 'name' => 'Максим', 'age' => 44], ['id' => 5, 'name' => 'Василий', 'age' => 32, 'is_admin' => true], ['id' => 7, 'name' => 'Роман', 'age' => 58], ] */

whereBetween()

Фильтрует элементы коллекции по диапазону переданного значения. Противоположность метода whereNotBetween().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$users = collect([ ['id' => 1, 'name' => 'Илья', 'age' => 8], ['id' => 2, 'name' => 'Роман', 'age' => 22], ['id' => 3, 'name' => 'Максим', 'age' => 6], ['id' => 4, 'name' => 'Семён', 'age' => 17], ['id' => 5, 'name' => 'Василий', 'age' => 24], ]);   /* Найдем пользователей, которым от 1 до 10 лет */ $youngGuys = $users->whereBetween('age', [1, 10]);   $youngGuys->all(); /* [ ['id' => 1, 'name' => 'Илья', 'age' => 8], ['id' => 3, 'name' => 'Максим', 'age' => 6], ] */

whereNotBetween()

Фильтрует (удаляет) элементы коллекции по диапазону переданного значения. Противоположность метода whereBetween().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$collection = collect([ ['product' => 'Стол', 'price' => 5000], ['product' => 'Стул', 'price' => 3500], ['product' => 'Шкаф', 'price' => 12000], ['product' => 'Тумбочка', 'price' => 3700], ['product' => 'Кровать', 'price' => 9500], ]);   $collection->whereNotBetween('price', [3000, 4000])->all(); /* [ ['product' => 'Стол', 'price' => 5000], ['product' => 'Шкаф', 'price' => 12000], ['product' => 'Кровать', 'price' => 9500], ] */

whereIn(), whereInStrict()

Фильтрует элементы коллекции по ключу/значению, содержащимся в переданном массиве.

whereInStrict() отличается от whereIn() тем, что производит строгое сравнение (помимо значения, сравнивает ещё и тип данных, а не делает приведение).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$articles = collect([ ['id' => 1, 'title' => 'Первая статья', 'category' => 117], ['id' => 2, 'title' => 'Вторая статья', 'category' => 56], ['id' => 3, 'title' => 'Третья статья', 'category' => 98], ['id' => 4, 'title' => 'Четвертая статья', 'category' => '117'], ['id' => 5, 'title' => 'Пятая статья', 'category' => 1], ]);   /* Нестрогое сравнение */ $articles->whereIn('category', [98, 117])->all(); /* [ ['id' => 1, 'title' => 'Первая статья', 'category' => 117], ['id' => 3, 'title' => 'Третья статья', 'category' => 98], ['id' => 4, 'title' => 'Четвертая статья', 'category' => '117'], ] */   /* Строгое сравнение */ $articles->whereInStrict('category', [98, 117])->all(); /* [ ['id' => 1, 'title' => 'Первая статья', 'category' => 117], ['id' => 3, 'title' => 'Третья статья', 'category' => 98], ] */

whereNotIn(), whereNotInStrict()

Фильтрует (удаляет) элементы коллекции по ключу/значению, содержащимся в переданном массиве.

whereNotInStrict() отличается от whereNotIn() тем, что производит строгое сравнение (помимо значения, сравнивает ещё и тип данных, а не делает приведение).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$articles = collect([ ['id' => 1, 'title' => 'Первая статья', 'category' => 117], ['id' => 2, 'title' => 'Вторая статья', 'category' => 56], ['id' => 3, 'title' => 'Третья статья', 'category' => 98], ['id' => 4, 'title' => 'Четвертая статья', 'category' => '117'], ['id' => 5, 'title' => 'Пятая статья', 'category' => 1], ]);   /* Нестрогое сравнение */ $articles->whereNotIn('category', [98, 117])->all(); /* [ ['id' => 2, 'title' => 'Вторая статья', 'category' => 56], ['id' => 5, 'title' => 'Пятая статья', 'category' => 1], ] */   /* Строгое сравнение */ $articles->whereNotInStrict('category', [98, 117])->all(); /* [ ['id' => 2, 'title' => 'Вторая статья', 'category' => 56], ['id' => 4, 'title' => 'Четвертая статья', 'category' => '117'], ['id' => 5, 'title' => 'Пятая статья', 'category' => 1], ] */

whereInstanceOf()

Фильтрует элементы коллекции по переданному типу класса.

$collection = collect([
    new User(),
    new Post(),
    new Admin(), // extends User
    new User(),
    new Task(),
]);
 
$collection->whereInstanceOf(User::class)->all();
// [App\User, App\Admin, App\User]

whereNotNull()

Возвращает все элементы коллекции, где значение не является null. Может работать как с простыми коллекциями, так и многомерными (но в таком случае нужно передать ключ в качестве аргумента). Противоположность метода whereNull().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
$collection = collect([0, null, '', [], false]);   $collection->whereNotNull()->all(); // [0, null, '', [], false]   $collection = collect([ ['id' => 1, 'value' => 0], ['id' => 2, 'value' => null], ['id' => 3, 'value' => ''], ['id' => 4, 'value' => []], ['id' => 5, 'value' => false], ]);   $collection->whereNotNull('value')->all(); /* [ ['id' => 1, 'value' => 0], ['id' => 3, 'value' => ''], ['id' => 4, 'value' => []], ['id' => 5, 'value' => false], ] */

whereNull()

Возвращает все элементы коллекции, где значение является null. Может работать как с простыми коллекциями, так и многомерными (но в таком случае нужно передать ключ в качестве аргумента). Противоположность метода whereNotNull().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
$collection = collect([0, null, '', [], false, null]);   $collection->whereNull()->all(); // [1 => null, 5 => null]   $collection = collect([ ['id' => 1, 'value' => 0], ['id' => 2, 'value' => null], ['id' => 3, 'value' => ''], ['id' => 4, 'value' => []], ['id' => 5, 'value' => false], ['id' => 6, 'value' => null], ]);   $collection->whereNull('value')->all(); /* [ ['id' => 2, 'value' => null], ['id' => 6, 'value' => null], ] */

first()

Возвращает первый элемент коллекции. Если передать первым аргументом callback-функцию, то будет возвращен первый элемент, который удовлетворяет этому условию.

В качестве второго аргумента можно установить значение по умолчанию, которое будет возвращено, если не найден ни один подходящий элемент коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$collection->first(); // 1   /* Вернем первое число, которое делится на 2 без остатка (но не самое 2) */ $collection->first( fn ($value, $key) => $value !== 2 && $value % 2 === 0 ); // 4   /* Попросим несуществующее значение. Должно вернуть значение по умолчанию */ $collection->first( fn ($value) => $value === 1111, 'default' ); // default

firstWhere()

Возвращает первый элемент коллекции с заданным ключом и значением. Также можно использовать оператор сравнения, если передать его в качестве аргумента.

Если передать только ключ (без значения), то будет возвращен первый элемент где такой ключ существует и его значение является истинным.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$users = collect([ ['name' => 'Илья', 'age' => null], ['name' => 'Роман', 'age' => 23], ['name' => 'Глеб', 'age' => 84], ['name' => 'Максим', 'age' => 14], ]);   $users->firstWhere('name', 'Максим'); // ['name' => 'Максим', 'age' => 14]   $users->firstWhere('age', '>', '25'); // ['name' => 'Глеб', 'age' => 84]   $users->firstWhere('age'); // ['name' => 'Роман', 'age' => 23]

shift()

Удаляет и возвращает первый элемент коллекции.

$collection = collect([1, 2, 3, 4, 5]);
 
$collection->shift();
// 1
 
$collection->all();
// [2, 3, 4, 5]

last()

Возвращает последний элемент коллекции. Если передать первым аргументом callback-функцию, то будет возвращен последний элемент, который удовлетворяет этому условию.

В качестве второго аргумента можно установить значение по умолчанию, которое будет возвращено, если не найден ни один подходящий элемент коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);   $collection->last(); // 9   /* Вернем первое число, которое делится на 2 без остатка */ $collection->last( fn ($value, $key) => $value % 2 === 0 ); // 8   /* Попросим несуществующее значение. Должно вернуть значение по умолчанию */ $collection->last( fn ($value) => $value === 1111, 'default' ); // default

pop()

Удаляет и возвращает последний элемент коллекции.

$collection = collect([1, 2, 3, 4, 5]);
 
$collection->pop();
// 5
 
$collection->all();
// [1, 2, 3, 4]

prepend()

Добавляет элемент в начало коллекции. В качестве второго аргумента можно передать строку с ключом, который будет установлен этому элементу.

$collection = collect([1, 2, 3, 4, 5]);
 
$collection->prepend(0);
$collection->all();
// [0, 1, 2, 3, 4, 5]
 
$collection = collect(['один' => 1, 'два' => 2]);
$collection->prepend(0, 'ноль');
$collection->all();
// ['ноль' => 0, 'один' => 1, 'два' => 2]

push()

Добавляет элемент коллекции в конец коллекции.

$collection = collect([1, 2, 3, 4]);
 
$collection->push(5);
 
$collection->all();
// [1, 2, 3, 4, 5]

pull()

Удаляет и возвращает элемент коллекции по переданному ключу.

$table = collect(['id' => 512, 'name' => 'Стол', 'price' => 5000]);
 
$table->pull('id');
// 512
 
$table->all();
// ['name' => 'Стол', 'price' => 5000]

put()

Устанавливает значение по переданному ключу. Если такого ключа не существует - добавляет новый элемент в конец коллекции.

1 2 3 4 5 6 7 8
$table = collect(['id' => 512, 'name' => 'Стол', 'price' => 5000]);   $table ->put('price', 7500) ->put('description', 'Он стоит!');   $table->all(); // ['id' => 512, 'name' => 'Стол', 'price' => 7500, 'description' => 'Он стоит!']

random()

Возвращает случайный элемент(ы) коллекции.

$collection = collect([1, 2, 3, 4, 5]);
 
$collection->random();
// 4 (выводит случайным образом)
 
$collection->random(2);
// [1, 3] (выводит случайным образом)

shuffle()

Случайным образом перемешивает элементы коллекции. В качестве аргумента можно передать seed (параметр переинициализации).

$collection = collect([1, 2, 3, 4, 5]);
 
$collection->shuffle();
// [4, 3, 1, 5, 2] (мешается случайным образом)
 
$collection->shuffle(1111);
// [5, 2, 3, 4, 1] (всегда в таком порядке при seed 1111)

each()

Делает перебор элементов коллекции на основе callback-функции. Аналог стандартного PHP оператора foreach() для коллекций.

Аргумент этого метода принимает callback-функцию, которая в свою очередь принимает два аргумента - значение и ключ.

Если необходимо прекратить цикл - нужно использовать return false, если необходимо пропустить какой-то элемент - нужно возвращать пустоту, используя return.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
$collection = collect(['Ноль', 'Один', 'Два', 'Три', 'Четыре', 'Пять', 'Шесть']);   /* * Выведем на экран все цифры без, которые делятся на 2 и не больше 4 */ $collection->each(function ($value, $key) { if ($key > 4) { return false; // Ключ элемента больше чем 4, завершим цикл }   if ($key === 0 || $key % 2 !== 0) { return; // Не делится на 2 без остатка, перейдем к следующему элементу коллекции }   echo $value . PHP_EOL; });   /* * Два * Четыре */   /* * Это тоже самое, что: * * foreach ($collection->toArray() as $key => $value) { * if ($key > 4) { * break; * } * * if ($key === 0 || $key % 2 !== 0) { * continue; * } * * echo $value . PHP_EOL; * } */

eachSpread()

Делает перебор элементов коллекции, передавая каждое значение вложенного элемента в callback-функцию.

В отличие от each(), позволяет делать перебор коллекций, элементы которых состоят из массивов, более читабельным (за счёт обращения к именованным аргументам, а не к $value).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
$users = collect([ ['Егор', 11, 'Тюмень'], // Можно использовать и массив ['Роман', 23, 'Москва'], collect(['Денис', 16, 'Берлин']), // ... и коллекции ]);   $users->eachSpread(function ($name, $age, $city) { if ($age >= 18) { return; }   echo "Пользователю $name из г. $city менее 18-ти лет!\n"; });   /* * Пользователю Егор из г. Тюмень менее 18-ти лет! * Пользователю Денис из г. Берлин менее 18-ти лет! */   /* * Если делать с помощью обычного each() - будет менее читабельно: * * $users->each(function ($value, $key) { * if ($value[1] >= 18) { * return; * } * * echo "Пользователю {$value[0]} из г. {$value[2]} менее 18-ти лет!\n"; * }); */

Как и в each(), можно использовать return (для перехода к следующему элементу) и return false (для прекращения цикла).

reduce()

Перебирает каждый элемент коллекции и передает полученный в конкретном цикле результат к следующей итерации.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$users = collect([ ['id' => 1, 'name' => 'Роман', 'balance' => 350, 'is_admin' => true], ['id' => 2, 'name' => 'Елизавета', 'balance' => 1200], ['id' => 3, 'name' => 'Максим', 'balance' => 540], ['id' => 4, 'name' => 'Егор', 'balance' => 3720], ]);   /* Посчитаем баланс всех пользователей, исключая администраторов */ $totalUserBalance = $users->reduce(function ($carry, $value) { return $carry + (empty($value['is_admin']) ? $value['balance'] : 0); });   echo $totalUserBalance; // 5460

Начальное значение $carry - всегда null. Если нужно это изменить - передайте новое значение во второй аргумент при вызове метода.

map()

Перебирает каждый элемент коллекции и передаёт его в callback-функцию, которая, в свою очередь, может вернуть измененное значение, формируя тем самым новую - "измененную" коллекцию.

1 2 3 4 5 6 7 8 9 10 11 12
$notTrimmedStr = collect([ ' тест ', 'trimmed_already', '/ ещё один тест ', ]);   $trimmedStr = $notTrimmedStr->map( fn($value, $key) => (string)Str::of($value)->trim('/ ') );   $trimmedStr->all(); // ['тест', 'trimmed_already', 'ещё один тест']

transform()

Массово изменяет элементы коллекции через callback-функцию. По сути, это тоже самое, что и map(), за единственным исключением: он изменяет вызываемую коллекцию, а не создает новый экземпляр класса.

$collection = collect([1, 2, 3]);
 
$collection->transform(fn($value, $key) => /* ... */ $value);
 
// Тоже самое что и:
$collection = $collection->map(fn($value, $key) => /* ... */ $value);

mapInto()

Делает перебор элементов коллекции и создает новый экземпляр переданного в метод класса, передав в его конструктор значение коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
class User { /** @var string */ private $name;   /** * User constructor. * * @param string $name */ public function __construct(string $name) { $this->name = $name; } }   // Клиентский код $userNames = collect(['Роман', 'Виталий', 'Егор']);   $users = $userNames->mapInto(User::class);   $users->all(); /* [ User { name: 'Роман' }, User { name: 'Виталий' }, User { name: 'Егор' }, ] */

mapSpread()

Делает перебор элементов коллекции, передавая каждое значение вложенного элемента в callback-функцию, которая, в свою очередь, может вернуть измененное значение, формируя тем самым новую - "измененную" коллекцию.

В отличие от map(), позволяет делать перебор коллекций, элементы которых состоят из массивов, более читабельным (за счёт обращения к именованным аргументам, а не к $value).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
$users = collect([ [1, 'роман'], [2, 'егор'], [3, 'александр'] ]);   // Сделаем так, чтобы имена были с заглавной буквы $users = $users->mapSpread(fn($id, $name) => [$id, Str::ucfirst($name)]);   $users->all();   /* * [ * [1, 'Роман'], * [2, 'Егор'], * [3, 'Александр'], * ] */   /* * Можно было это сделать и с помощью map(), но выглядит это не очень красиво: * * $users = $users->map(fn($values) => [$values[0], Str::ucfirst($values[1])]); */

mapToGroups()

Перебирает все элементы коллекции и группирует их используя callback-функцию.

Callback-функция должна вернуть ассоциативный массив, содержащий одну пару ключ => значение, таким образом формируя новый набор сгруппированных значений.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
$users = collect([ ['id' => 1, 'name' => 'Роман', 'country' => 'Россия', 'city' => 'Москва'], ['id' => 2, 'name' => 'Том', 'country' => 'США', 'city' => 'Нью-Йорк'], ['id' => 3, 'name' => 'Глеб', 'country' => 'Россия', 'city' => 'Санкт-Петербург'], ['id' => 4, 'name' => 'Джордж', 'country' => 'США', 'city' => 'Вашингтон'], ['id' => 5, 'name' => 'Алексей', 'country' => 'Россия', 'city' => 'Уфа'], ['id' => 6, 'name' => 'Патрик', 'country' => 'Австралия', 'city' => 'Сидней'], ]);   $usersLocations = $users->mapToGroups( fn($value, $key) => [$value['country'] => $value['city']] );   $usersLocations->toArray();   /* [ 'Россия' => ['Москва', 'Санкт-Петербург', 'Уфа'], 'США' => ['Нью-Йорк','Вашингтон'], 'Австралия' => ['Сидней'], ] */

mapWithKeys()

Перебирает все элементы коллекции через callback-функцию и создаёт новую коллекцию. Отличается от mapToGroup() тем, что не создаёт массив с повторяющиеся значениями, а перезаписывает их, если ключ уже существует.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$collection = collect([ ['name' => 'Сергей', 'email' => 'sergey@test.com'], ['name' => 'Роман', 'email' => 'roma1991@mail.ru'], ['name' => 'Роман', 'email' => 'roman@sarvarov.dev'], ]);   $keyed = $collection->mapWithKeys( fn($item) => [$item['name'] => $item['email']] );   $keyed->all(); /* [ 'Сергей' => 'sergey@test.com', 'Роман' => 'roman@sarvarov.dev', ] */

flatten()

Преобразует многомерную коллекцию (коллекцию с несколькими уровнями) в одномерную.

1 2 3 4 5 6 7 8 9
$collection = collect([ 'name' => 'Роман', 'languages' => ['php', 'sql', 'javascript', 'css', 'html'], ]);   $flattened = $collection->flatten();   $flattened->all(); // ['Роман', 'php', 'sql', 'javascript', 'css', 'html']

Можно передать глубину уровней в качестве аргумента:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$collection = collect([ 'уровень 1' => [ 'уровень 2' => [ 'уровень 3', ], ], ]);   $flattened = $collection->flatten(1);   $flattened->all(); /* [ ['уровень 3'], ] */

flatMap()

Также как и map(), перебирает каждый элемент коллекции и передаёт его в callback-функцию, которая, в свою очередь, может вернуть измененное значение, формируя тем самым новую - "измененную" коллекцию. После этого сглаживает коллекцию на 1 уровень.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$collection = collect([ ['name' => 'Роман'], ['age' => 23], ['country' => 'Россия'], ['city' => 'Москва'], ]);   $flattened = $collection->flatMap( fn($values) => array_map('mb_strtoupper', $values) );   $flattened->all(); /* [ 'name' => 'РОМАН', 'age' => '23', 'country' => 'РОССИЯ', 'city' => 'МОСКВА', ] */

flip()

Меняет местами ключи и их значения.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$collection = collect([ 'ключ' => 'значение', 'было ключом' => 'стало значением', ]);   $flipped = $collection->flip();   $flipped->all(); /* [ 'значение' => 'ключ', 'стало значением' => 'было ключом', ] */

forget()

Удаляет элемент коллекции по его ключу. Также можно передать массив ключей, которые нужно удалить. Аналог PHP функции unset.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
$roman = collect([ 'name' => 'Роман', 'age' => 23, 'city' => 'Москва', 'password' => '$2y$10$nsipFleZ3hQkrmhW3N40aOFMqT.swZyyb/TgZ1JUu3H1QRMhxZ3Wq', 'email' => 'roman@sarvarov.dev', 'phone' => '+7 (999) 123-45-67', ]);   // Можно удалить единственный ключ $roman->forget('password');   // Можно удалить несколько ключей сразу $roman->forget(['phone', 'email']);   // Можно использовать PHP функцию unset() unset($roman['city']);   $roman->all(); // ['name' => 'Роман', 'age' => 23]

forPage()

Позволяет разбить коллекцию на страницы и возвращает какую-то из них. В аргументе нужно передать номер страницы и кол-во элементов на одной странице.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]);
 
// Возьмём 3 элементы с начала второй страницы:
$chunk = $collection->forPage(2, 3);
 
$chunk->all();
// [4, 5, 6]

groupBy()

Группирует элементы коллекции по переданному ключу.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
$users = collect([ ['name' => 'Роман', 'city' => 'Москва'], ['name' => 'Том', 'city' => 'Нью-Йорк'], ['name' => 'Глеб', 'city' => 'Москва'], ['name' => 'Патрик', 'city' => 'Сидней'], ]);   // Разделим коллекцию на группы по городам $usersCities = $users->groupBy('city');   $usersCities->toArray(); /* [ 'Москва' => [ ['name' => 'Роман', 'city' => 'Москва'], ['name' => 'Глеб', 'city' => 'Москва'] ], 'Нью-Йорк' => [ ['name' => 'Том', 'city' => 'Нью-Йорк'], ], 'Сидней' => [ ['name' => 'Патрик', 'city' => 'Сидней'], ], ] */

Можно передать несколько ключей в виде массива для многоуровневой группировки:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
$users = collect([ ['name' => 'Роман', 'country' => 'Россия', 'city' => 'Москва'], ['name' => 'Олег', 'country' => 'Украина', 'city' => 'Одесса'], ['name' => 'Евгений', 'country' => 'Россия', 'city' => 'Липецк'], ['name' => 'Антонина', 'country' => 'Беларусь', 'city' => 'Гомель'], ['name' => 'Герман', 'country' => 'Украина', 'city' => 'Одесса'], ['name' => 'Анатолий', 'country' => 'Казахстан', 'city' => 'Караганда'], ]);   $usersByLocations = $users->groupBy(['country', 'city']);   $usersByLocations->toArray(); /* [ 'Россия' => [ 'Москва' => [ ['name' => 'Роман', 'country' => 'Россия', 'city' => 'Москва'], ], 'Липецк' => [ ['name' => 'Евгений', 'country' => 'Россия', 'city' => 'Липецк'], ], ], 'Украина' => [ 'Одесса' => [ ['name' => 'Олег', 'country' => 'Украина', 'city' => 'Одесса'], ['name' => 'Герман', 'country' => 'Украина', 'city' => 'Одесса'], ], ] 'Беларусь' => [ 'Гомель' => [ ['name' => 'Антонина', 'country' => 'Беларусь', 'city' => 'Гомель'], ], ], 'Казахстан' => [ 'Караганда' => [ ['name' => 'Анатолий', 'country' => 'Казахстан', 'city' => 'Караганда'], ], ], ] */

Вместо ключа, в качестве аргумента можно передать callback-функцию:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
// Допустим, есть работники, с которыми можно связаться по одному номеру телефона $workers = collect([ ['name' => 'Роман', 'phone_number' => '+7 495 123-33-44'], ['name' => 'Ольга', 'phone_number' => '84951233344'], ['name' => 'Петр', 'phone_number' => '8 (499) 987-65-43'], ['name' => 'Анна', 'phone_number' => '+7 499 987-65-43'], ]);   // Как мы видим, они в разном формате. Давайте сгруппируем их, используя callback-функцию $phoneNumbers = $workers->groupBy(function ($value, $key) { $phoneNumber = Str::of(preg_replace('/\D/', '', $value['phone_number']));   // Если номер телефона начинается на 7, заменим на 8 if ($phoneNumber->startsWith('7')) { $phoneNumber = $phoneNumber->replaceFirst('7', '8'); }   return (string) $phoneNumber; });   $phoneNumbers->toArray(); /* [ '84951233344' => [ ['name' => 'Роман', 'phone_number' => '+7 495 123-33-44'], ['name' => 'Ольга', 'phone_number' => '84951233344'], ], '84999876543' => [ ['name' => 'Петр', 'phone_number' => '8 (499) 987-65-43'], ['name' => 'Анна''phone_number' => '+7 499 987-65-43'], ], ] */

Если вам нужно сохранить ключи элементов, то необходимо передать true в качестве второго аргумента. Если не передать - ключи будут потеряны во время группировки.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
$users = collect([ 'user_564' => ['name' => 'Роман', 'city' => 'Москва'], 'user_110' => ['name' => 'Вацлав', 'city' => 'Варшава'], 'user_1097' => ['name' => 'Петр', 'city' => 'Минск'], 'user_849' => ['name' => 'Вениамин', 'city' => 'Москва'], ]);   $usersByLocations = $users->groupBy('city', true);   $usersByLocations->toArray(); /* [ 'Москва' => [ 'user_564' => ['name' => 'Роман', 'city' => 'Москва'], 'user_849' => ['name' => 'Вениамин', 'city' => 'Москва'], ], 'Варшава' => [ 'user_110' => ['name' => 'Вацлав', 'city' => 'Варшава'], ], 'Минск' => [ 'user_1097' => ['name' => 'Петр', 'city' => 'Минск'], ], ] */   /* * Если не установить в preserveKeys true, то вернулось бы так:   * [ * 'Москва' => [ * ['name' => 'Роман', 'city' => 'Москва'], * ['name' => 'Вениамин', 'city' => 'Москва'], * ], * 'Варшава' => [ * ['name' => 'Вацлав', 'city' => 'Варшава'], * ], * 'Минск' => [ * ['name' => 'Петр', 'city' => 'Минск'], * ], * ] */

has()

Проверяет существование ключа в коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$collection = collect(['account_id' => 1, 'product' => 'Стол', 'amount' => 5]);   $collection->has('product'); // true   $collection->has(['product', 'amount']); // true   $collection->has(['amount', 'price']); // false   /* * Будет тот же результат, если использовать стандартные средства PHP: * * isset($collection['product']) // true * isset($collection['product'], $collection['amount']) // true * isset($collection['amount'], $collection['price']) // false */

intersect()

Удаляет все значения коллекции, которые отсутствуют в переданном массиве. Можно передать не массив, а строку с одним значением.

$collection = collect(['Стул', 'Стол', 'Шкаф']);
 
$intersect = $collection->intersect(['Стул', 'Шкаф', 'Подоконник']);
 
$intersect->all();
// ['Стул', 'Шкаф']

intersectByKeys()

Удаляет все ключи коллекции, которые отсутствуют в переданном массиве. Как и в intersect() - можно передать не массив, а строку с одним значением.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$users = collect([ ['id' => 1, 'name' => 'Роман', 'is_admin' => true], ['id' => 2, 'name' => 'Елизавета'], ['id' => 3, 'name' => 'Максим'], ]);   $admins = $users->intersectByKeys('is_admin'); // Можно передать и несколько значений в виде массива: ['is_admin', 'name'] и т.д.   $admins->all(); /* [ ['id' => 1, 'name' => 'Роман', 'is_admin' => true] ] */

isEmpty()

Проверяет, пустая ли коллекция и возвращает true (если пустая) или false (если в ней есть хотя бы один элемент). Противоположность метода isNotEmpty().

collect([])->isEmpty();
// true
 
collect([1, 2, 3])->isEmpty();
// false

isNotEmpty()

Проверяет, пустая ли коллекция и возвращает true, если в ней есть хотя бы один элемент, или false, если она пустая. Противоположность метода isEmpty().

collect([])->isNotEmpty();
// false
 
collect([1, 2, 3])->isNotEmpty();
// true

implode()

Возвращает строку с чередованием элементов коллекции через переданный в аргумент функции разделитель. Работает по аналогии стандартной в PHP функции implode().

Если коллекция многомерная, то первым аргументом указывается ключ, значения которого нужно чередовать.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/* Простая коллекция */ $friends = collect(['Рома', 'Миша', 'Петя'])->implode(', ');   echo "Пошли как-то $friends в бар..."; // Пошли как-то Рома, Миша, Петя в бар...   /* Многомерная коллекция */ $friends = collect([ ['id' => 1, 'name' => 'Рома', 'city' => 'Москва'], ['id' => 2, 'name' => 'Миша', 'city' => 'Москва'], ['id' => 3, 'name' => 'Петя', 'city' => 'Москва'], ])->implode('name', ', ');   echo "Пошли как-то $friends в бар..."; // Пошли как-то Рома, Миша, Петя в бар...

join()

Возвращает строку с чередованием элементов коллекции через переданный в аргумент функции разделитель. Отличается от метода implode() тем, что работать может только с одномерными коллекциями (не умеет чередовать по ключам), а также может принимать второй аргумент - последний разделитель.

collect(['а', 'б', 'в'])->join(', '); // а, б, в
collect(['а', 'б', 'в'])->join(', ', ' и '); // а, б и в
collect(['а', 'б'])->join(', ', ' и '); // а и б
collect(['а'])->join(', ', ' и '); // а

keyBy()

Устанавливает ключ к элементам коллекции, беря за основу значение переданного ключа.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$users = collect([ ['id' => 113, 'name' => 'Роман'], ['id' => 567, 'name' => 'Борис'], ['id' => 392, 'name' => 'Артур'], ]);   $keyed = $users->keyBy('id');   $keyed->all(); /* [ 113 => ['id' => 113, 'name' => 'Роман'], 567 => ['id' => 567, 'name' => 'Борис'], 392 => ['id' => 392, 'name' => 'Артур'], ] */

Как и во многих других методах коллекции, вместо названия ключа можно передать callback-функцию:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$users = collect([ ['id' => 113, 'name' => 'Роман'], ['id' => 567, 'name' => 'Борис'], ['id' => 392, 'name' => 'Артур'], ]);   $keyed = $users->keyBy(fn($value) => "user_{$value['id']}");   $keyed->all(); /* [ 'user_113' => ['id' => 113, 'name' => 'Роман'], 'user_567' => ['id' => 567, 'name' => 'Борис'], 'user_392' => ['id' => 392, 'name' => 'Артур'], ] */

keys()

Возвращает все ключи элементов коллекции.

1 2 3 4 5 6 7 8 9 10 11 12
$cities = collect([ 'Москва' => ['country' => 'Россия'], 'Хельсинки' => ['country' => 'Финляндия'], 'Сан-Диего' => ['country' => 'США'], ]);   $cities->keys()->all(); /* ['Москва', 'Хельсинки', 'Сан-Диего']   Такой же результат будет если сделать array_keys($cities->all()) */

sum()

Возвращает сумму элементов коллекции. Можно передать callback-функцию со своей логикой подсчёта суммы, либо же передать строку с ключом, значения которого нужно суммировать.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
$collection = collect([1, 2, 3, 4, 5, 4, 3, 2, 1]);   /* Сумма все элементов */ $collection->sum(); // 25   /* Сумма элементов в многомерной коллекции (баланс пользователей) */ $users = collect([ ['id' => 1, 'name' => 'Роман', 'balance' => 95000, 'is_admin' => true], ['id' => 2, 'name' => 'Петр', 'balance' => 500], ['id' => 3, 'name' => 'Евгений', 'balance' => 1100], ['id' => 4, 'name' => 'Елизавета', 'balance' => 200], ['id' => 5, 'name' => 'Рената', 'balance' => 450], ]);   $users->sum('balance'); // 97250   /* Найдем баланс пользователей, которые не являются администраторами */ $users->sum( fn($item) => ($item['is_admin'] ?? false) === false ? $item['balance'] : 0 ); // 2250

min()

Возвращает минимальное значение среди элементов коллекции. Можно передать callback-функцию со своей логикой определения наименьшего значения, либо же передать строку с ключом, по которому сравнивать элементы.

Противоположность метода max().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$numbers = collect([1, 6, 20]);   /* Наименьшее значение */ $numbers->min(); // 1   /* Наименьшее значение, но не менее чем чем 3 */ $numbers->max(fn($item) => $item >= 3 ? $item : null); // 6   /* Наименьшее значение ключа */ $users = collect([ ['name' => 'Роман', 'age' => 23], ['name' => 'Денис', 'age' => 35], ['name' => 'Егор', 'age' => 14], ]);   $users->min('age'); // 14

max()

Возвращает максимальное значение среди элементов коллекции. Можно передать callback-функцию со своей логикой определения наибольшего значения, либо же передать строку с ключом, по которому сравнивать элементы.

Противоположность метода min().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$numbers = collect([1, 6, 2, 20, 5, 3, 4]);   /* Наибольшее значение */ $numbers->max(); // 20   /* Наибольшее значение, но не более чем 10 */ $numbers->max(fn($item) => $item <= 10 ? $item : null); // 6   /* Наибольшее значение ключа */ $users = collect([ ['name' => 'Роман', 'age' => 23], ['name' => 'Денис', 'age' => 35], ['name' => 'Егор', 'age' => 14], ]);   $users->max('age'); // 35

median()

Возвращает значение медианы среди элементов коллекции. Можно не передавать никаких аргументов, а можно передать название ключа, по значениям которого сравнивать, или же callback-функцию.

$median = collect([1, 1, 2, 4])->median(); // 1.5
 
$users = collect([
    ['name' => 'Роман', 'age' => 23],
    ['name' => 'Денис', 'age' => 35],
    ['name' => 'Егор', 'age' => 14],
]);
 
$users->median('age'); // 23

mode()

Возвращает значение моды среди элементов коллекции. Можно не передавать никаких аргументов, а можно передать название ключа, по значениям которого сравнивать, или же callback-функцию.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
$mode = collect([1, 2, 3])->mode(); // [1, 2, 3]   $mode = collect([1, 1, 2, 4])->mode(); // [1]   $users = collect([ ['name' => 'Роман', 'age' => 23], ['name' => 'Денис', 'age' => 35], ['name' => 'Ольга', 'age' => 33], ['name' => 'Сергей', 'age' => 28], ['name' => 'Дмитрий', 'age' => 35], ['name' => 'Павел', 'age' => 23], ['name' => 'Анна', 'age' => 24], ['name' => 'Егор', 'age' => 14], ]);   $mode = $users->mode('age'); // [23, 35]

merge()

Объединяет коллекцию с переданным в аргументе массивом или другой коллекцией.

Если переданные элементы содержат числовые ключи, то они будут добавлены к исходной коллекции. Если же передаются элементы со строковыми ключами и таких ключи уже есть в исходной коллекции, то значения будут перезаписаны значениями передаваемых элементов.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$collection = collect([1, 2, 3, 4]);   $merged = $collection->merge([5, 6, 7, 8]); $merged->all(); // [1, 2, 3, 4, 5, 6, 7, 8]   $merged = $collection->merge([1, 2, 3, 4]); $merged->all(); // [1, 2, 3, 4, 1, 2, 3, 4]   $collection = collect(['id' => 1, 'price' => 100]); $merged = $collection->merge(['price' => 200, 'discount' => false]); $merged->all(); // ['id' => 1, 'price' => 200, 'discount' => false]

mergeRecursive()

Объединяет коллекцию с переданным в аргументе массивом или другой коллекцией. Отличается от merge() тем, что значения элементов не будут перезаписываться, а будут помещены в совместный массив.

1 2 3 4 5 6
$collection = collect(['id' => 1, 'price' => 100]);   $merged = $collection->mergeRecursive(['id' => 2, 'price' => 200, 'discount' => false]);   $merged->all(); // ['id' => [1, 2], 'price' => [100, 200], 'discount' => false]

replace()

Объединяет коллекцию с переданным в аргументе массивом или другой коллекцией, перезаписывая при этом повторяющиеся значения ключей.

Ведет себя аналогично методу merge(), однако, в дополнение к перезаписи соответствующих элементов строковыми ключами, метод replace() также перезапишет элементы в коллекции, которые имеют соответствующие числовые ключи.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
$collection = collect([1, 2, 3, 4]);   $replaced = $collection->replace([5, 6, 7, 8]); $replaced->all(); // [1, 2, 3, 4, 5, 6, 7, 8]   $replaced = $collection->replace([1, 2, 3, 4]); $replaced->all(); // [1, 2, 3, 4]   $collection = collect(['id' => 1, 'price' => 100]); $replaced = $collection->replace(['price' => 200, 'discount' => false]); $replaced->all(); // ['id' => 1, 'price' => 200, 'discount' => false]

replaceRecursive()

Объединяет коллекцию с переданным в аргументе массивом или другой коллекцией, перезаписывая при этом повторяющиеся значения ключей.

От replace() отличается тем, что выполняет это действие рекурсивно (на вложенные массивы и коллекции).

1 2 3 4 5 6
$collection = collect(['id' => 1, 'price' => 100, 'categories' => [1, 2, 3]]);   $replaced = $collection->replaceRecursive(['price' => 200, 'discount' => false, 'categories' => [3 => 4]]);   $replaced->all(); // ['id' => 1, 'price' => 200, 'discount' => false, 'categories' => [1, 2, 3, 4]]

union()

Объединяет коллекцию с переданным в аргументе массивом или другой коллекцией. От merge() и replace() отличается тем, что данные исходной коллекции не будут перезаписываться.

$user = collect(['id' => 1, 'name' => 'Роман', 'balance' => 5000]);
 
$newUser = $user->union(['balance' => 10000, 'is_subscribed' => true]);
 
$newUser->all();
// ['id' => 1, 'name' => 'Роман', 'balance' => 5000, 'is_subscribed' => true]

zip()

Объединяет все значения заданного массива со значениями исходной коллекции на соответствующем индексе.

$products = collect(['Стол', 'Стул', 'Шкаф']);
$prices = [5000, 3500, 8000, 9999];
// $prices = collect([5000, 3500, 8000, 9999]);
 
$products->zip($prices)->toArray();
// [['Стол', 5000], ['Стул', 3500], ['Шкаф', 8000], [null, 9999]]

collect()

Возвращает новый экземпляр коллекции с данными исходной коллекции. Результат этого метода будет идентичен, если просто склонировать коллекцию с помощью PHP оператора clone, за исключением ситуаций, когда необходимо преобразовать ленивую коллекцию в обычную (см. Ленивые коллекции).

$collectionA = collect([1, 2, 3]);
// Collection #1 { [1, 2, 3] }
 
$collectionB = $collectionA->collect();
// Collection #2 { [1, 2, 3] }
 
$collectionC = clone $collectionA;
// Collection #3 { [1, 2, 3] }

make()

Статический метод. Создает новый экземпляр коллекции. Чаще всего к нему прибегают при создании ленивых коллекций, в других случаях используют collect(), что, по сути, одно и тоже (см. Создание коллекции).

macro()

Статический метод. Позволяет регистрировать пользовательские методы коллекций (см. Расширение коллекций).

times()

Статический метод. Создает новую коллекцию путем выполнения callback-функции определенное количество раз.

/* Получим с пятью последними годами */
$currentYear = now()->year;
 
$collection = Collection::times(5, 
    fn($number) => $currentYear - $number
);
 
$collection->all();
// [2015, 2016, 2017, 2018, 2019]

nth()

Создаёт новую коллекцию каждые n элементов. Во втором аргумент можно указать отклонение от начала коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$collection = collect([ 'П', 'H', 'р', 'e', 'и', 'l', 'в', 'l', 'е', 'o', 'т', ]);   $hello = $collection->nth(2); $hello->implode(''); // Привет   $hello = $collection->nth(2, 1); $hello->implode(''); // Hello

pad()

Заполняет коллекцию переданным значением до определенной длины. Если указать отрицательное значение, то заполнение начнется сначала коллекции.

$collection = collect(['А', 'Б', 'В']);
 
$padded= $collection->pad(5, 0);
$padded->all();
// ['А', 'Б', 'В', 0, 0]
 
$padded = $collection->pad(-5, 0);
$padded->all();
// [0, 0, 'А', 'Б', 'В']

partition()

Делит элементы на две коллекции. В качестве аргумента принимает callback-функцию. Если эта callback-функция вернет true - то этот элемент пойдет в первую коллекцию, если false или ничего не вернет - то во вторую.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
$users = collect([ ['id' => 1, 'name' => 'Роман', 'is_admin' => true], ['id' => 2, 'name' => 'Борис', 'is_admin' => false], ['id' => 3, 'name' => 'Евгений', 'is_admin' => false], ['id' => 4, 'name' => 'Ксения', 'is_admin' => true], ['id' => 5, 'name' => 'Александр', 'is_admin' => false], ]);   /** @var Collection $admins */ /** @var Collection $users */ [$admins, $users] = $users->partition( /* ^ можно использовать list() */ fn($value) => ($value['is_admin'] ?? false) === true );   $admins->all(); /* [ ['id' => 1, 'name' => 'Роман', 'is_admin' => true], ['id' => 4, 'name' => 'Ксения', 'is_admin' => true], ] */   $users->all(); /* [ ['id' => 2, 'name' => 'Борис', 'is_admin' => false], ['id' => 3, 'name' => 'Евгений', 'is_admin' => false], ['id' => 5, 'name' => 'Александр', 'is_admin' => false], ] */

tap()

Передает коллекцию callback-функции и возвращает объект этой коллекции. Можно делать различного рода операции и вычисления внутри callback-функции, при этом продолжить выполнение других методов цепным способом, так как tap() всегда возвращает объект коллекции.

$sum = null;
 
$collection = collect([1, 2, 3, 4, 5, 6, 7, 9])
    ->tap(function (Collection $collection) use (&$sum) {
        $sum = $collection->sum();
 
        Log::debug("Сумма элементов коллекции: {$sum}.");
    });
 
echo $sum; // 37

pipe()

Передает коллекцию в заданную функцию и возвращает результат.

От tap() отличается тем, что в tap() - неважно, что возвращает callback-функция - всегда будет возвращен объект коллекции. Метод pipe() же возвращает результат callback-функции - это может быть как объект, так и другое значение.

Удобно использовать, когда нужно выполнить или абстрагировать какой-то код в процессе манипуляции над коллекцией.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$collection = collect([1, 2, 3, 4, 5]);   /** @var Collection $piped */ $piped = $collection->pipe(function (Collection $collection) { if ($collection->sum() < 10) { Log::debug('Сумма коллекции меньше 10, возвращаем исходную коллекцию.');   return $collection; }   Log::debug('Сумма коллекции больше или равно 10, возвращаем перевернутую коллекцию.');   return $collection->reverse(); });   $piped->all(); // [5, 4, 3, 2, 1]

reverse()

Меняет порядок элементов в коллекции в обратную сторону (зеркалит коллекцию), сохраняя при этом ключи.

$collection = collect(['а', 'б', 'в', 'г', 'д']);
 
$reversed = $collection->reverse();
 
$reversed->all();
// ['д', 'г', 'в', 'б', 'а']

sort()

Сортирует коллекцию по возрастанию. Сохраняет ключи (если нужно сбросить ключи, после сортировки примените к коллекции метод values()). Противоположность метода sortDesc().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$collection = collect([5, 3, 1, 2, 4]);   /* По возрастанию */ $sorted = $collection->sort()->values(); $sorted->all(); // [1, 2, 3, 4, 5]   /* Сначала те, которые делятся на 2 без остатка */ $sorted = $collection->sort(function ($a, $b) { if ($a % 2 === $b % 2) { return $a <=> $b; }   return $a % 2 === 0 ? -1 : 1; });   $sorted->all(); // [2, 4, 1, 3, 5]

sort() в своей работе вызывает uasort(), о сортировке через которую можно прочитать в документации к PHP.

sortDesc()

Сортирует коллекцию в обратном порядке (от большего к меньшему). Противоположность метода sort(), однако, в отличие от которой, не может принимать callback-функцию в качестве аргумента.

$collection = collect([1, 5, 3, 2, 4]);
 
$sorted = $collection->sortDesc()->values();
 
$sorted->all();
// [5, 4, 3, 2, 1]

sortBy(), sortByDesc()

Сортируют коллекцию по значениям переданного ключа. Сохраняют ключи (если нужно сбросить ключи, после сортировки примените к коллекции метод values()).

sortBy() сортирует от меньшего к большему, sortByDesc() - наоборот.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$products = collect([ ['name' => 'Стул', 'colors' => ['Чёрный', 'Коричневый']], ['name' => 'Стол', 'colors' => ['Чёрный']], ['name' => 'Шкаф', 'colors' => ['Белый', 'Чёрный', 'Коричневый']], ]);   /* Отсортируем по количеству доступных цветов */   // Запишем анонимную функцию в переменную (для удобства демонстрации примера) $sortByColorsCallback = fn($product, $key) => count($product['colors']);   $products->sortBy($sortByColorsCallback)->values()->all(); /* [ ['name' => 'Стол', 'colors' => ['Чёрный']], ['name' => 'Стул', 'colors' => ['Чёрный', 'Коричневый']], ['name' => 'Шкаф', 'colors' => ['Белый', 'Чёрный', 'Коричневый']], ] */   /* Тоже самое, только в обратном порядке */ $products->sortByDesc($sortByColorsCallback)->values()->all(); /* [ ['name' => 'Шкаф', 'colors' => ['Белый', 'Чёрный', 'Коричневый']], ['name' => 'Стул', 'colors' => ['Чёрный', 'Коричневый']], ['name' => 'Стол', 'colors' => ['Чёрный']], ] */

sortKeys(), sortKeysDesc()

Сортируют элементы коллекции по их ключам. sortKeys() сортирует от меньшего к большему, sortKeysDesc() - наоборот.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
$collection = collect([ 999 => 'три', 111 => 'один', 555 => 'два', ]);   $collection->sortKeys()->all(); /* [ 111 => 'один', 555 => 'два', 999 => 'три', ] */   $collection->sortKeysDesc()->all(); /* [ 999 => 'три', 555 => 'два', 111 => 'один', ] */

values()

Сбрасывает ключи у элементов коллекции и возвращает результат.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
$collection = collect([ 11 => 'один', 12 => 'два', 13 => 'три', 14 => 'четыре', 15 => 'пять', ])->values();   $collection->all(); // ['один', 'два', 'три', 'четыре', 'пять']   $collection = collect([ 'key1' => 'один', 'key2' => 'два', 'key3' => 'три', ])->values();   $collection->all(); // ['один', 'два', 'три']

take()

Возвращает новую коллекцию с заданным числом элементов (обрезает коллекцию). Можно передать отрицательное значение, тогда будут возвращены элементы с конца коллекции. Противоположность метода skip().

Сохраняет ключи, если нужно их сбросить - примените к коллекции метод values().

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
 
$collection->take(4)->all();
// [1, 2, 3, 4]
 
$collection->take(-3)->values()->all();
// [8, 9, 10]

takeUntil()

Перебирает элементы коллекции с начала и оставляя все элементы, пока callback-функция не вернет true, после чего возвращает новую коллекцию. Является противоположностью метода takeWhile().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$users = collect([ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ]);   /* Оставим только тех, кто родился в 20 веке */ $adultUsers = $users->takeUntil( fn($value) => $value['born_at'] >= 2000 );   $adultUsers->all(); /* [ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ] */

Если коллекция одномерная, то можно не передавать callback-функцию, а передать значение, до наступления которого будут оставлены все элементы:

$collection = collect(['один', 'два', 'три', 'четыре', 'пять']);
 
$subset = $collection->takeUntil('три');
 
$subset->all();
// ['один', 'два']

takeWhile()

Перебирает элементы коллекции с начала и оставляя все элементы, пока callback-функция не вернет false, после чего возвращает новую коллекцию. Является противоположностью метода takeUntil().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$users = collect([ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ]);   /* Оставим только тех, кто родился в 20 веке */ $minorUsers = $users->takeWhile( fn($value) => $value['born_at'] < 2000 );   $minorUsers->all(); /* [ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ] */

skip()

Возвращает новую коллекцию, пропустив (удалив) первые n элементов. Противоположность метода take().

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

skipUntil()

Перебирает элементы коллекции с начала и пропуская (удаляя) все элементы, пока callback-функция не вернет true, после чего возвращает новую коллекцию. Противоположность метода skipWhile().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
$users = collect([ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ]);   /* Оставим только тех, кто родился в 21 веке */ $minorUsers = $users->skipUntil( fn($value) => $value['born_at'] >= 2000 );   $minorUsers->all(); /* [ ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ] */

Если коллекция одномерная, то можно не передавать callback-функцию, а передать значение, до наступления которого будут удалены все элементы:

$collection = collect(['один', 'два', 'три', 'четыре', 'пять']);
 
$skipped = $collection->skipUntil('три');
 
$skipped->all();
// ['три', 'четыре', 'пять']

skipWhile()

Перебирает элементы коллекции с начала и пропуская (удаляя) все элементы, пока callback-функция не вернет false, после чего возвращает новую коллекцию. Противоположность метода skipUntil().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
$users = collect([ ['id' => 1, 'name' => 'Вениамин', 'born_at' => 1987], ['id' => 2, 'name' => 'Петр', 'born_at' => 1993], ['id' => 3, 'name' => 'Елена', 'born_at' => 1995], ['id' => 4, 'name' => 'Игорь', 'born_at' => 1996], ['id' => 5, 'name' => 'Ксения', 'born_at' => 1999], ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ]);   /* Оставим только тех, кто родился в 21 веке */ $minorUsers = $users->skipWhile( fn($value) => $value['born_at'] < 2000 );   $minorUsers->all(); /* [ ['id' => 6, 'name' => 'Ирина', 'born_at' => 2003], ['id' => 7, 'name' => 'Екатерина', 'born_at' => 2003], ['id' => 8, 'name' => 'Алексей', 'born_at' => 2006], ] */

slice()

Возвращает коллекцию, начиная с переданного индекса (остальные элементы будут удалены). Ключи при этом сохранятся (если не нужно - примените к коллекции метод values()).

Если нужно ограничить кол-во получаемых элементов, можно передать число с необходимым количеством во второй аргумент вызываемого метода.

$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
 
$slice = $collection->slice(4);
$slice->values()->all();
// [5, 6, 7, 8, 9, 10]
 
$slice = $collection->slice(2, 3);
$slice->values()->all();
// [3, 4, 5]

splice()

Возвращает элементы коллекции, начиная с переданного индекса. От метода slice() отличается тем, что удаляет полученные элементы из исходной коллекции.

Если нужно ограничить кол-во получаемых элементов, можно передать число с необходимым количеством во второй аргумент вызываемого метода.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
$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]

Кроме этого, метод принимает 3-й аргумент - значение (или массив значений), которые будут подставлены в исходную коллекцию вместо удаленных элементов.

1 2 3 4 5 6 7 8 9 10 11
$hello = collect(['Привет', ', ', 'Роман', '!']);   echo $hello->implode(''); // Привет, Роман!   $userName = $hello->splice(2, 1, ['Уважаемый ', 'посетитель']); $userName->all(); // ['Роман']   echo $hello->implode(''); // Привет, Уважаемый посетитель!

split()

Разделяет коллекцию на несколько частей.

$collection = collect([1, 2, 3, 4, 5]);
 
$groups = $collection->split(3);
 
$groups->toArray();
// [[1, 2], [3, 4], [5]]

when()

Выполняет callback-функцию если в первом аргументе было передано true. Противоположность метода unless().

В качестве третьего аргумента можно передать ещё одну callback-функцию, которая выполнится по умолчанию.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
$collection = collect();   $collection->when(true, function (Collection $collection) { /* Этот код выполнится, так как мы передаем true */ return $collection->push('один'); });   $collection->when(false, function (Collection $collection) { /* Этот код НЕ выполнится, так как мы передаем false */ return $collection->push('два'); });   $collection->when(false, function (Collection $collection) { /* Этот код НЕ выполнится, так как мы передаем false */ return $collection->push('три'); }, function (Collection $collection) { /* Но при этом выполнится этот код (по умолчанию) */ return $collection->push('четыре'); });   $collection->all(); // ['один', 'четыре']

unless()

Выполняет callback-функцию если в первом аргументе было передано false. Противоположность метода when().

В качестве третьего аргумента можно передать ещё одну callback-функцию, которая выполнится по умолчанию.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
$collection = collect();   $collection->unless(false, function (Collection $collection) { /* Этот код выполнится, так как мы передаем false */ return $collection->push('один'); });   $collection->unless(true, function (Collection $collection) { /* Этот код НЕ выполнится, так как мы передаем true */ return $collection->push('два'); });   $collection->unless(true, function (Collection $collection) { /* Этот код НЕ выполнится, так как мы передаем true */ return $collection->push('три'); }, function (Collection $collection) { /* Но при этом выполнится этот код (по умолчанию) */ return $collection->push('четыре'); });   $collection->all(); // ['один', 'четыре']

whenNotEmpty(), unlessEmpty()

Выполняет callback-функцию если коллекция не пустая. Противоположность методов whenEmpty(), unlessNotEmpty().

В качестве второго аргумента можно передать ещё одну callback-функцию, которая выполнится по умолчанию.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$collection = collect();   $collection->whenNotEmpty(function (Collection $collection) { /* Этот код НЕ выполнится, так как $collection пустая */ return $collection->push('один'); }); // []   $collection->unlessEmpty(function (Collection $collection) { /* Этот код НЕ выполнится, так как $collection пустая */ return $collection->push('два'); }, function (Collection $collection) { /* Но при этом выполнится этот код (код по умолчанию) */ return $collection->push('три'); });   $collection->all(); // ['три']   $collection->whenNotEmpty(function (Collection $collection) { /* Этот код выполнится, так как $collection не пустая */ return $collection->push('четыре'); });   $collection->all(); // ['три', 'четыре']

whenEmpty(), unlessNotEmpty()

Выполняет callback-функцию если коллекция пустая. Противоположность методов whenNotEmpty(), unlessEmpty().

В качестве второго аргумента можно передать ещё одну callback-функцию, которая выполнится по умолчанию.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
$collection = collect();   $collection->whenEmpty(function (Collection $collection) { /* Этот код выполнится, так как $collection пустая */ return $collection->push('один'); }); // ['один']   $collection->unlessNotEmpty(function (Collection $collection) { /* Этот код НЕ выполнится, так как $collection не пустая */ return $collection->push('два'); }, function (Collection $collection) { /* Но при этом выполнится этот код (код по умолчанию) */ return $collection->push('три'); });   $collection->all(); // ['один', 'три']   $collection->whenEmpty(function (Collection $collection) { /* Этот код НЕ выполнится, так как $collection не пустая */ return $collection->push('четыре'); });   $collection->all(); // ['один', 'три']

wrap()

Статический метод. Все значения, которые в него передаются - обернутся в коллекцию. Если передать коллекцию, то ничего не произойдет и вернется она же. Противоположность метода unwrap().

1 2 3 4 5 6 7 8 9 10
Collection::wrap(null)->all(); // Collection { [] } Collection::wrap([]); // Collection { [] } Collection::wrap(''); // Collection { [''] }   Collection::wrap(1); // Collection { [1] } Collection::wrap('строка'); // Collection { ['строка'] } Collection::wrap(true); // Collection { [true] }   Collection::wrap(['строка', 'в', 'массиве']); // Collection { ['строка', 'в', 'массиве'] } Collection::wrap(collect(['строка', 'в', 'коллекции'])); // Collection { ['строка', 'в', 'коллекции'] }

unwrap()

Статический метод. Если в него передать коллекцию, то вернется преобразованный массив (через метод all()). В остальных случаях вернется то, что изначально передавалось. Противоположность метода wrap().

Collection::unwrap(null); // null
Collection::unwrap(1); // 1
Collection::unwrap('строка'); // строка
Collection::unwrap(['массив']); // ['массив']
Collection::unwrap(collect(['коллекция'])); // ['коллекция']

toJson()

Конвертирует элементы коллекции в формат JSON.

1 2 3 4 5 6 7 8
$collection = collect([ ['id' => 1, 'name' => 'Роман'], ['id' => 2, 'name' => 'Анна'], ['id' => 3, 'name' => 'Борис'], ]);   echo $collection->toJson(); // [{"id":1,"name":"\u0420\u043e\u043c\u0430\u043d"},{"id":2,"name":"\u0410\u043d\u043d\u0430"},{"id":3,"name":"\u0411\u043e\u0440\u0438\u0441"}]

dump()

Выводит информацию о переменных коллекции (используется для отладки).

1 2 3 4 5 6 7 8 9 10 11 12 13
$collection = collect([ 'Коллекции', 'это', 'просто', ]);   $collection->dump();   /* Collection { ['Коллекции', 'это', 'просто'] } */

dd()

Выводит информацию о переменных коллекции и завершает выполнение программы. По факту, этот метод делает dump(), а затем завершает скрипт с помощью die().

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
$collection = collect([ 'Коллекции', 'это', 'просто', ]);   $collection->dd();   /* Collection { ['Коллекции', 'это', 'просто'] } */   echo 'Hey!'; // Этот код уже не выполнится, так как dd() завершает работу программы

Расширение коллекций

Коллекциям можно добавлять пользовательские методы с помощью статичного метода macro(), который будет вызван перед выполнением метода.

В примере ниже мы создадим новый метод toUpper(), который будет преобразовывать все значения элементов коллекции в верхний регистр.

Collection::macro('toUpper', function () {
    return $this->map(
        fn($item, $key) => Str::upper($item)
    );
});
 
$collection = collect(['один', 'два', 'три']);
 
$collection->toUpper()->all();
// ['ОДИН', 'ДВА', 'ТРИ']

Хорошей практикой будет регистрировать ваши методы в провайдерах.

Например, можно сделать новый провайдер CollectionServiceProvider выполнив в консоли следующую команду: php artisan make:provider CollectionServiceProvider, после чего в методе register() зарегистрировать все пользовательские методы коллекций способом, который указан выше.

Расширение коллекций моделей Eloquent

Если вам нужно создать какой-то специфичный метод только для одной/нескольких моделей, можно поступить следующим образом:

  1. Создать новый класс коллекции, который будет наследоваться от базового класса Collection. Хорошим вариантом будет сделать папку /app/Collections.
    Пример содержимого файла UserCollection.php (пользовательской коллекции для модели User):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
<?php   namespace App\Collections;   use Illuminate\Support\Collection;   /** * Пользовательская коллекция для модели \App\User. */ class UserCollection extends Collection { /** * Фильтрует коллекцию. Оставляет только пользователей-администраторов. * * @return mixed */ public function allAdmins() { return $this->filter->is_admin; // Используются сообщения высшего порядка, но можно и прибегнуть к методам } }
  1. В самой модели (в нашем примере используется модель User) переопределить публичный метод newCollection().
public function newCollection(array $models = [])
{
    return new UserCollection($models);
}

На этом всё. Теперь, при создании экземпляра этой модели, или же при получении её из БД, можно применять пользовательский метод allAdmins().

1 2 3
$users = User::all(); $users->allAdmins()->toArray(); // Вернется коллекциями с пользователями, у которых is_admin = true

Сообщения высшего порядка

Коллекции в Laravel поддерживают сообщения высшего порядка (higher order messages), которые упрощают выполнение каких-то общих действий и делает ваш код ещё читабельнее.

Подробно на этом разделе останавливаться не будем - это тема для отдельного туториала. Если говорить вкратце, то каждое сообщение высшего порядка может быть доступно как динамическое свойство в экземпляре коллекции.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* Пример 1 */ $users = collect([ ['id' => 1, 'name' => 'Илья', 'age' => 35], ['id' => 2, 'name' => 'Роман', 'age' => 23], ['id' => 3, 'name' => 'Глеб', 'age' => 84], ['id' => 4, 'name' => 'Максим', 'age' => 14], ]);   echo $users->sum->age; // 156   /* Пример 2 */ $employees->reject(function ($employee) { return $employee->isRetired(); })->each(function ($employee) { $employee->sendPayment(); });   // Используя сообщения высшего порядка: $employees->reject->isRetired()->each->sendPayment();

Ленивые коллекции

Позволяют работать с большими объемами данных, сохраняя при этом небольшое потребление памяти. Использует генераторы PHP.

1 2 3 4 5 6 7 8 9 10 11 12 13 14
//$hugeCollection = Collection::times(1 * 1000000); // Создается   //$hugeCollection = Collection::times(10 * 1000000); // Ошибка: Allowed memory size of 536870912 bytes exhausted   $hugeCollection = LazyCollection::times(10 * 1000000); // Создается   $powed = $hugeCollection->map( fn($number) => $number ** 2 );   $powed->all();

Создание ленивой коллекции

Чтобы создать экземпляр ленивой коллекции, необходимо передать функцию PHP генератора в метод make().

$hugeCollection = LazyCollection::make(function () {
    for ($i = 0; $i < 10000000; $i++) {
        yield $i;
    }
});
 
$hugeCollection->each(function ($item) {
    echo "$item <br />";
});

Методы ленивой коллекции

В ленивой коллекции доступны почти все методы обычной коллекции, за исключением тех, которые изменяют исходную коллекцию: shift(), pop(), prepend() и др.

Кроме того, ленивые коллекции имеют ряд методов, которые не представлены в обычной коллекции:

tapEach()

При использовании метода each(), вызов его callback-функции по отношению к элементам коллекции идёт сразу. tapEach() же вызывает свой callback только если это понадобится.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
$lazyCollection = LazyCollection::make(function () { for ($i = 0; $i < 3; $i++) { yield $i; } });   /* Обычный each() */ $lazyCollection->each(function ($item) { echo 'Этот код выполнится и покажется на экран.<br />'; }); /* Этот код выполнится и покажется на экран. Этот код выполнится и покажется на экран. Этот код выполнится и покажется на экран. */   /* tapEach() */ $lazyCollection = $lazyCollection->tapEach(function ($item) { echo 'Этот код выполнится только по требованию.<br />'; }); // (ничего)   $lazyCollection->all(); /* Этот код выполнится только по требованию. Этот код выполнится только по требованию. Этот код выполнится только по требованию. */

remember()

Возвращает новую ленивую коллекцию, которая запомнит все значения, которые уже были перечислены, и не получит их снова при повторном перечислении коллекции.

$users = User::cursor()->remember();
// запросы в БД не делаются
 
$users->take(5)->all();
// Выполнится запрос и 5 первых пользователей будут взяты из БД
 
$users->take(20)->all();
// Первые 5 пользователей будут взяты из кэша, остальные - из БД

Коллекции или массивы?

Несмотря на то, что использовать коллекции очень удобно, это не означает, что нужно полностью отказываться от использования массивов [].

Исходя из моего опыта, я пришел к следующему выводу:

  1. Если вы не создавали коллекцию, а получили её откуда-то - не переводите без надобности в массив.
  2. Держитесь принципа KISS (Keep It Simple Stupid - делайте вещи проще). Если вам нужно произвести какую-то простую операцию - не стоит создавать объект массива - решите эту простую задачу средствами PHP.
/* Не стоит лишний раз создавать экземпляр коллекции */
// $numbers = collect([1, 2, 3]);
// $sum = $numbers->sum();
 
/* Сделайте выбор в пользу более простого варианта */
$numbers = [1, 2, 3];
$sum = array_sum($numbers);
// 6
  1. Возможность массового использования коллекций зависит также и от вашей команды. Все ли разработчики, которые работают с вами, хорошо владеют коллекциями и легко смогут понять ваш код?

Источник: Laravel.com

Комментарии

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: