Идёт обновление сайта. Несколько дней возможны сбои в оформлении и переводах. Документация работает — если страница выглядит сломанной, обновите её позже.

Документация
L Laravel L intervention/image
Войти
Главная Laravel 10.x Коллекции

Коллекции

10.x 7 мар 2026 г.

#Введение

Класс Illuminate\Support\Collection предоставляет удобную и цепочную оболочку для работы с массивами данных. Например, рассмотрите следующий код. Мы используем хелпер collect для создания нового экземпляра коллекции из массива, применяем функцию strtoupper к каждому элементу, а затем удаляем все пустые элементы:

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

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

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

Как упоминалось выше, хелпер collect возвращает новый экземпляр Illuminate\Support\Collection для заданного массива. Таким образом, создание коллекции сводится к следующему:

$collection = collect([1, 2, 3]);
Примечание

Результаты запросов Eloquent всегда возвращаются в виде экземпляров Collection.

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

Коллекции поддерживают "macroable" — возможность добавлять дополнительные методы в класс Collection во время выполнения. Метод macro класса Illuminate\Support\Collection принимает замыкание, которое будет выполнено при вызове вашего макроса. Внутри макроса можно обращаться к другим методам коллекции через $this, как если бы это был настоящий метод класса коллекции. Например, следующий код добавляет метод toUpper в класс Collection:

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

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

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

$upper = $collection->toUpper();

// ['FIRST', 'SECOND']

Обычно макросы коллекций следует объявлять в методе boot service provider.

#Аргументы макроса

При необходимости можно определить макросы, принимающие дополнительные аргументы:

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

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

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

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

#Доступные методы

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

<style> .collection-method-list > p { columns: 10.8em 3; -moz-columns: 10.8em 3; -webkit-columns: 10.8em 3; } .collection-method-list a { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } </style>

#Список методов

<style> .collection-method code { font-size: 14px; } .collection-method:not(.first-collection-method) { margin-top: 50px; } </style>

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

Метод all возвращает базовый массив, представленный коллекцией:

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

// [1, 2, 3]

#average() {.collection-method}

Псевдоним для метода avg.

#avg() {.collection-method}

Метод avg возвращает среднее значение для заданного ключа:

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

// 20

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

// 2

#chunk() {.collection-method}

Метод chunk разбивает коллекцию на несколько меньших коллекций заданного размера:

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

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

$chunks->all();

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

Этот метод особенно полезен в представлениях при работе с сетками, например, в Bootstrap. Например, представьте, что у вас есть коллекция моделей Eloquent, которую нужно отобразить в сетке:

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

#chunkWhile() {.collection-method}

Метод chunkWhile разбивает коллекцию на несколько меньших коллекций на основе результата переданного колбэка. Переменная $chunk, передаваемая в замыкание, может использоваться для проверки предыдущего элемента:

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

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

$chunks->all();

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

#collapse() {.collection-method}

Метод collapse сворачивает коллекцию массивов в одну плоскую коллекцию:

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

$collapsed = $collection->collapse();

$collapsed->all();

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

#collect() {.collection-method}

Метод collect возвращает новый экземпляр Collection с элементами, которые в данный момент находятся в коллекции:

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

$collectionB = $collectionA->collect();

$collectionB->all();

// [1, 2, 3]

Метод collect особенно полезен для преобразования ленивых коллекций в стандартные экземпляры Collection:

$lazyCollection = LazyCollection::make(function () {
    yield 1;
    yield 2;
    yield 3;
});

$collection = $lazyCollection->collect();

$collection::class;

// 'Illuminate\Support\Collection'

$collection->all();

// [1, 2, 3]
Примечание

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

#combine() {.collection-method}

Метод combine объединяет значения коллекции в качестве ключей с значениями другого массива или коллекции:

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

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

$combined->all();

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

#concat() {.collection-method}

Метод concat добавляет значения указанного array или коллекции в конец другой коллекции:

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

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

$concatenated->all();

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

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

#contains() {.collection-method}

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

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

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

// false

Или вы можете передать строку в метод contains, чтобы проверить, содержит ли коллекция заданное значение элемента:

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

$collection->contains('Desk');

// true

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

// false

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

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

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

// false

Метод contains использует "нестрогие" сравнения при проверке значений элементов, то есть строка с числовым значением будет считаться равной целому числу с тем же значением. Для "строгих" сравнений используйте метод containsStrict.

Для противоположного поведения contains используйте метод doesntContain.

#containsOneItem() {.collection-method}

Метод containsOneItem определяет, содержит ли коллекция ровно один элемент:

collect([])->containsOneItem();

// false

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

// true

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

// false

#containsStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод contains, но все значения сравниваются с использованием "строгих" сравнений.

Примечание

Поведение этого метода изменено при использовании Eloquent Collections.

#count() {.collection-method}

Метод count возвращает общее количество элементов в коллекции:

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

$collection->count();

// 4

#countBy() {.collection-method}

Метод countBy подсчитывает количество вхождений значений в коллекции. По умолчанию метод подсчитывает вхождения каждого элемента, позволяя считать определённые "типы" элементов в коллекции:

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

$counted = $collection->countBy();

$counted->all();

// [1 => 1, 2 => 3, 3 => 1]

Вы можете передать замыкание в метод countBy, чтобы подсчитать все элементы по пользовательскому значению:

$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']);

$counted = $collection->countBy(function (string $email) {
    return substr(strrchr($email, "@"), 1);
});

$counted->all();

// ['gmail.com' => 2, 'yahoo.com' => 1]

#crossJoin() {.collection-method}

Метод crossJoin выполняет декартово произведение значений коллекции с заданными массивами или коллекциями, возвращая все возможные комбинации:

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

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

$matrix->all();

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

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

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

$matrix->all();

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

#dd() {.collection-method}

Метод dd выводит элементы коллекции и завершает выполнение скрипта:

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

$collection->dd();

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

Если вы не хотите останавливать выполнение скрипта, используйте метод dump.

#diff() {.collection-method}

Метод diff сравнивает коллекцию с другой коллекцией или простым PHP array по значениям. Этот метод вернёт значения из исходной коллекции, которых нет в указанной коллекции:

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

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

$diff->all();

// [1, 3, 5]
Примечание

Поведение этого метода изменено при использовании Eloquent Collections.

#diffAssoc() {.collection-method}

Метод diffAssoc сравнивает коллекцию с другой коллекцией или с обычным PHP array по ключам и значениям. Этот метод вернёт пары ключ/значение из исходной коллекции, которых нет в указанной коллекции:

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

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

$diff->all();

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

#diffAssocUsing() {.collection-method}

В отличие от diffAssoc, метод diffAssocUsing принимает пользовательскую функцию обратного вызова для сравнения индексов:

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

$diff = $collection->diffAssocUsing([
    'Color' => 'yellow',
    'Type' => 'fruit',
    'Remain' => 3,
], 'strnatcasecmp');

$diff->all();

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

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

#diffKeys() {.collection-method}

Метод diffKeys сравнивает коллекцию с другой коллекцией или простым PHP array по ключам. Этот метод вернёт пары ключ/значение из исходной коллекции, которых нет в заданной коллекции:

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

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

$diff->all();

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

#doesntContain() {.collection-method}

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

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

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

// false

Или вы можете передать строку в метод doesntContain, чтобы проверить, не содержит ли коллекция заданное значение элемента:

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

$collection->doesntContain('Table');

// true

$collection->doesntContain('Desk');

// false

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

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

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

// true

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

#dot() {.collection-method}

Метод dot преобразует многомерную коллекцию в одноуровневую коллекцию, используя "dot" нотацию для обозначения глубины:

$collection = collect(['products' => ['desk' => ['price' => 100]]]);

$flattened = $collection->dot();

$flattened->all();

// ['products.desk.price' => 100]

#dump() {.collection-method}

Метод dump выводит элементы коллекции:

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

$collection->dump();

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

Если вы хотите остановить выполнение скрипта после вывода коллекции, используйте метод dd.

#duplicates() {.collection-method}

Метод duplicates извлекает и возвращает дублирующиеся значения из коллекции:

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

$collection->duplicates();

// [2 => 'a', 4 => 'b']

Если коллекция содержит массивы или объекты, вы можете передать ключ атрибута, по которому хотите проверить дубликаты:

$employees = collect([
    ['email' => 'abigail@example.com', 'position' => 'Developer'],
    ['email' => 'james@example.com', 'position' => 'Designer'],
    ['email' => 'victoria@example.com', 'position' => 'Developer'],
]);

$employees->duplicates('position');

// [2 => 'Developer']

#duplicatesStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод duplicates, но все значения сравниваются с использованием "строгих" сравнений.

#each() {.collection-method}

Метод each перебирает элементы коллекции и передаёт каждый элемент в замыкание:

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

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

Если вы хотите прекратить перебор элементов, вы можете вернуть false из замыкания:

$collection->each(function (int $item, int $key) {
    if (/* условие */) {
        return false;
    }
});

#eachSpread() {.collection-method}

Метод eachSpread перебирает элементы коллекции, передавая каждое вложенное значение в заданный колбэк:

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

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

Вы можете прекратить перебор элементов, вернув false из колбэка:

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

#ensure() {.collection-method}

Метод ensure используется для проверки, что все элементы коллекции принадлежат заданному типу или списку типов. В противном случае будет выброшено исключение UnexpectedValueException:

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

return $collection->ensure([User::class, Customer::class]);

Примитивные типы, такие как string, int, float, bool и array, также могут быть указаны:

return $collection->ensure('int');
Внимание

Метод ensure не гарантирует, что элементы других типов не будут добавлены в коллекцию позже.

#every() {.collection-method}

Метод every проверяет, что все элементы коллекции проходят заданный тест истинности:

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

// false

Если коллекция пуста, метод every возвращает true:

$collection = collect([]);

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

// true

#except() {.collection-method}

Метод except возвращает все элементы коллекции, кроме тех, у которых указаны заданные ключи:

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

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

$filtered->all();

// ['product_id' => 1]

Для противоположного поведения except используйте метод only.

Примечание

Поведение этого метода изменено при использовании Eloquent Collections.

#filter() {.collection-method}

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

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

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

$filtered->all();

// [3, 4]

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

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

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

// [1, 2, 3]

Для противоположной операции filter используйте метод reject.

#first() {.collection-method}

Метод first возвращает первый элемент коллекции, который проходит заданное условие:

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

// 3

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

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

// 1

#firstOrFail() {.collection-method}

Метод firstOrFail идентичен методу first; однако, если результат не найден, будет выброшено исключение Illuminate\Support\ItemNotFoundException:

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

// Выбрасывает ItemNotFoundException...

Вы также можете вызвать метод firstOrFail без аргументов, чтобы получить первый элемент коллекции. Если коллекция пуста, будет выброшено исключение Illuminate\Support\ItemNotFoundException:

collect([])->firstOrFail();

// Выбрасывает ItemNotFoundException...

#firstWhere() {.collection-method}

Метод firstWhere возвращает первый элемент коллекции с заданной парой ключ / значение:

$collection = collect([
    ['name' => 'Regena', 'age' => null],
    ['name' => 'Linda', 'age' => 14],
    ['name' => 'Diego', 'age' => 23],
    ['name' => 'Linda', 'age' => 84],
]);

$collection->firstWhere('name', 'Linda');

// ['name' => 'Linda', 'age' => 14]

Вы также можете вызвать метод firstWhere с оператором сравнения:

$collection->firstWhere('age', '>=', 18);

// ['name' => 'Diego', 'age' => 23]

Как и метод where, вы можете передать один аргумент в метод firstWhere. В этом случае метод firstWhere вернёт первый элемент, у которого значение указанного ключа считается истинным:

$collection->firstWhere('age');

// ['name' => 'Linda', 'age' => 14]

#flatMap() {.collection-method}

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

$collection = collect([
    ['name' => 'Sally'],
    ['school' => 'Arkansas'],
    ['age' => 28]
]);

$flattened = $collection->flatMap(function (array $values) {
    return array_map('strtoupper', $values);
});

$flattened->all();

// ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];

#flatten() {.collection-method}

Метод flatten преобразует многомерную коллекцию в одномерную:

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

$flattened = $collection->flatten();

$flattened->all();

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

При необходимости в метод flatten можно передать аргумент "глубина":

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

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

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

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

В этом примере вызов flatten без указания глубины также бы уплощал вложенные массивы, что привело бы к результату ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']. Указание глубины позволяет задать количество уровней вложенности, которые будут уплощены.

#flip() {.collection-method}

Метод flip меняет местами ключи и значения коллекции:

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

$flipped = $collection->flip();

$flipped->all();

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

#forget() {.collection-method}

Метод forget удаляет элемент из коллекции по его ключу:

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

$collection->forget('name');

$collection->all();

// ['framework' => 'laravel']
Внимание

В отличие от большинства других методов коллекции, forget не возвращает новую изменённую коллекцию; он изменяет коллекцию, на которой вызывается.

#forPage() {.collection-method}

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

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

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

$chunk->all();

// [4, 5, 6]

#get() {.collection-method}

Метод get возвращает элемент по заданному ключу. Если ключ не существует, возвращается null:

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

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

// taylor

Вы можете опционально передать значение по умолчанию вторым аргументом:

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

$value = $collection->get('age', 34);

// 34

Вы даже можете передать callback в качестве значения по умолчанию. Результат callback будет возвращён, если указанный ключ не существует:

$collection->get('email', function () {
    return 'taylor@example.com';
});

// taylor@example.com

#groupBy() {.collection-method}

Метод groupBy группирует элементы коллекции по заданному ключу:

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

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

$grouped->all();

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

Вместо передачи строки key вы можете передать колбэк. Колбэк должен вернуть значение, по которому вы хотите сгруппировать:

$grouped = $collection->groupBy(function (array $item, int $key) {
    return substr($item['account_id'], -3);
});

$grouped->all();

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

Несколько критериев группировки можно передать в виде массива. Каждый элемент массива будет применён к соответствующему уровню в многомерном массиве:

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

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

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

#has() {.collection-method}

Метод has проверяет, существует ли заданный ключ в коллекции:

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

$collection->has('product');

// true

$collection->has(['product', 'amount']);

// true

$collection->has(['amount', 'price']);

// false

#hasAny() {.collection-method}

Метод hasAny проверяет, существует ли хотя бы один из заданных ключей в коллекции:

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

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

// true

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

// false

#implode() {.collection-method}

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

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

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

// Desk, Chair

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

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

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

Вы можете передать замыкание в метод implode, если хотите форматировать значения перед объединением:

$collection->implode(function (array $item, int $key) {
    return strtoupper($item['product']);
}, ', ');

// DESK, CHAIR

#intersect() {.collection-method}

Метод intersect удаляет из исходной коллекции все значения, которых нет в указанном array или коллекции. Результирующая коллекция сохранит ключи исходной коллекции:

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

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

$intersect->all();

// [0 => 'Desk', 2 => 'Chair']
Примечание

Поведение этого метода изменяется при использовании Eloquent Collections.

#intersectAssoc() {.collection-method}

Метод intersectAssoc сравнивает исходную коллекцию с другой коллекцией или array, возвращая пары ключ/значение, которые присутствуют во всех указанных коллекциях:

$collection = collect([
    'color' => 'red',
    'size' => 'M',
    'material' => 'cotton'
]);

$intersect = $collection->intersectAssoc([
    'color' => 'blue',
    'size' => 'M',
    'material' => 'polyester'
]);

$intersect->all();

// ['size' => 'M']

#intersectByKeys() {.collection-method}

Метод intersectByKeys удаляет из исходной коллекции все ключи и соответствующие значения, которые отсутствуют в переданном array или коллекции:

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

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

$intersect->all();

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

#isEmpty() {.collection-method}

Метод isEmpty возвращает true, если коллекция пуста; иначе — false:

collect([])->isEmpty();

// true

#isNotEmpty() {.collection-method}

Метод isNotEmpty возвращает true, если коллекция не пуста; иначе — false:

collect([])->isNotEmpty();

// false

#join() {.collection-method}

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

collect(['a', 'b', 'c'])->join(', '); // 'a, b, c'
collect(['a', 'b', 'c'])->join(', ', ', and '); // 'a, b, and c'
collect(['a', 'b'])->join(', ', ' and '); // 'a and b'
collect(['a'])->join(', ', ' and '); // 'a'
collect([])->join(', ', ' and '); // ''

#keyBy() {.collection-method}

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

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

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

$keyed->all();

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

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

$keyed = $collection->keyBy(function (array $item, int $key) {
    return strtoupper($item['product_id']);
});

$keyed->all();

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

#keys() {.collection-method}

Метод keys возвращает все ключи коллекции:

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

$keys = $collection->keys();

$keys->all();

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

#last() {.collection-method}

Метод last возвращает последний элемент коллекции, который проходит заданное условие:

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

// 2

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

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

// 4

#lazy() {.collection-method}

Метод lazy возвращает новый экземпляр LazyCollection на основе внутреннего массива элементов:

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

$lazyCollection::class;

// Illuminate\Support\LazyCollection

$lazyCollection->all();

// [1, 2, 3, 4]

Это особенно полезно, когда нужно выполнить преобразования над огромной Collection, содержащей много элементов:

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

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

#macro() {.collection-method}

Статический метод macro позволяет добавлять методы в класс Collection во время выполнения. Подробнее см. в разделе о расширении коллекций.

#make() {.collection-method}

Статический метод make создаёт новый экземпляр коллекции. См. раздел Создание коллекций.

#map() {.collection-method}

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

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

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

$multiplied->all();

// [2, 4, 6, 8, 10]
Внимание

Как и большинство других методов коллекции, map возвращает новый экземпляр коллекции; он не изменяет коллекцию, на которой вызывается. Если нужно изменить исходную коллекцию, используйте метод transform.

#mapInto() {.collection-method}

Метод mapInto() перебирает коллекцию, создавая новый экземпляр заданного класса, передавая значение в конструктор:

class Currency
{
    /**
     * Создаёт новый экземпляр валюты.
     */
    function __construct(
        public string $code
    ) {}
}

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

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

$currencies->all();

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

#mapSpread() {.collection-method}

Метод mapSpread перебирает элементы коллекции, передавая каждое вложенное значение в заданное замыкание. Замыкание может изменить элемент и вернуть его, формируя новую коллекцию изменённых элементов:

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

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

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

$sequence->all();

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

#mapToGroups() {.collection-method}

Метод mapToGroups группирует элементы коллекции с помощью заданного замыкания. Замыкание должно возвращать ассоциативный массив с одной парой ключ / значение, формируя новую коллекцию сгруппированных значений:

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

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

$grouped->all();

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

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

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

#mapWithKeys() {.collection-method}

Метод mapWithKeys перебирает коллекцию и передаёт каждое значение в заданный callback. Callback должен возвращать ассоциативный массив с одной парой ключ / значение:

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

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

$keyed->all();

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

#max() {.collection-method}

Метод max возвращает максимальное значение по заданному ключу:

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

// 20

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

// 5

#median() {.collection-method}

Метод median возвращает медиану по заданному ключу:

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

// 15

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

// 1.5

#merge() {.collection-method}

Метод merge объединяет переданный массив или коллекцию с исходной коллекцией. Если строковый ключ из переданных элементов совпадает с ключом в исходной коллекции, значение из переданных элементов перезапишет исходное:

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

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

$merged->all();

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

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

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

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

$merged->all();

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

#mergeRecursive() {.collection-method}

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

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

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

$merged->all();

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

#min() {.collection-method}

Метод min возвращает минимальное значение по заданному ключу:

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

// 10

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

// 1

#mode() {.collection-method}

Метод mode возвращает моду по заданному ключу:

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

// [10]

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

// [1]

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

// [1, 2]

#nth() {.collection-method}

Метод nth создаёт новую коллекцию, состоящую из каждого n-го элемента:

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

$collection->nth(4);

// ['a', 'e']

Вы можете опционально передать смещение начала в качестве второго аргумента:

$collection->nth(4, 1);

// ['b', 'f']

#only() {.collection-method}

Метод only возвращает элементы коллекции с указанными ключами:

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

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

$filtered->all();

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

Для противоположной операции only используйте метод except.

Примечание

Поведение этого метода изменяется при использовании Eloquent Collections.

#pad() {.collection-method}

Метод pad заполняет массив заданным значением до указанного размера. Этот метод работает аналогично функции 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, чтобы разделить элементы, которые проходят заданное условие, и те, которые не проходят:

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

[$underThree, $equalOrAboveThree] = $collection->partition(function (int $i) {
    return $i < 3;
});

$underThree->all();

// [1, 2]

$equalOrAboveThree->all();

// [3, 4, 5, 6]

#percentage() {.collection-method}

Метод percentage позволяет быстро определить процент элементов в коллекции, которые проходят заданное логическое условие:

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

$percentage = $collection->percentage(fn ($value) => $value === 1);

// 33.33

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

$percentage = $collection->percentage(fn ($value) => $value === 1, precision: 3);

// 33.333

#pipe() {.collection-method}

Метод pipe передаёт коллекцию в заданный замыкание и возвращает результат выполнения этого замыкания:

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

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

// 6

#pipeInto() {.collection-method}

Метод pipeInto создаёт новый экземпляр указанного класса и передаёт коллекцию в его конструктор:

class ResourceCollection
{
    /**
     * Создать новый экземпляр ResourceCollection.
     */
    public function __construct(
      public Collection $collection,
    ) {}
}

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

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

$resource->collection->all();

// [1, 2, 3]

#pipeThrough() {.collection-method}

Метод pipeThrough передаёт коллекцию в массив замыканий и возвращает результат выполнения этих замыканий:

use Illuminate\Support\Collection;

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

$result = $collection->pipeThrough([
    function (Collection $collection) {
        return $collection->merge([4, 5]);
    },
    function (Collection $collection) {
        return $collection->sum();
    },
]);

// 15

#pluck() {.collection-method}

Метод pluck извлекает все значения для заданного ключа:

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

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

$plucked->all();

// ['Desk', 'Chair']

Вы также можете указать, как должны быть индексированы элементы результирующей коллекции:

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

$plucked->all();

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

Метод pluck также поддерживает извлечение вложенных значений с помощью "dot" нотации:

$collection = collect([
    [
        'name' => 'Laracon',
        'speakers' => [
            'first_day' => ['Rosa', 'Judith'],
        ],
    ],
    [
        'name' => 'VueConf',
        'speakers' => [
            'first_day' => ['Abigail', 'Joey'],
        ],
    ],
]);

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

$plucked->all();

// [['Rosa', 'Judith'], ['Abigail', 'Joey']]

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

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

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

$plucked->all();

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

#pop() {.collection-method}

Метод pop удаляет и возвращает последний элемент коллекции:

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

$collection->pop();

// 5

$collection->all();

// [1, 2, 3, 4]

Вы можете передать целое число в метод pop, чтобы удалить и вернуть несколько элементов с конца коллекции:

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

$collection->pop(3);

// collect([5, 4, 3])

$collection->all();

// [1, 2]

#prepend() {.collection-method}

Метод prepend добавляет элемент в начало коллекции:

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

$collection->prepend(0);

$collection->all();

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

Вы также можете передать второй аргумент, чтобы указать ключ добавляемого элемента:

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

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

$collection->all();

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

#pull() {.collection-method}

Метод pull удаляет и возвращает элемент из коллекции по его ключу:

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

$collection->pull('name');

// 'Desk'

$collection->all();

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

#push() {.collection-method}

Метод push добавляет элемент в конец коллекции:

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

$collection->push(5);

$collection->all();

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

#put() {.collection-method}

Метод put устанавливает заданный ключ и значение в коллекции:

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

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

$collection->all();

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

#random() {.collection-method}

Метод random возвращает случайный элемент из коллекции:

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

$collection->random();

// 4 - (выбран случайно)

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

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

$random->all();

// [2, 4, 5] - (выбрано случайно)

Если в коллекции меньше элементов, чем запрошено, метод random выбросит исключение InvalidArgumentException.

Метод random также принимает замыкание, которое получит текущий экземпляр коллекции:

use Illuminate\Support\Collection;

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

$random->all();

// [1, 2, 3, 4, 5] - (выбрано случайно)

#range() {.collection-method}

Метод range возвращает коллекцию, содержащую целые числа в указанном диапазоне:

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

$collection->all();

// [3, 4, 5, 6]

#reduce() {.collection-method}

Метод reduce сводит коллекцию к одному значению, передавая результат каждой итерации в следующую:

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

$total = $collection->reduce(function (?int $carry, int $item) {
    return $carry + $item;
});

// 6

Значение $carry в первой итерации равно null; однако вы можете указать начальное значение, передав второй аргумент в reduce:

$collection->reduce(function (int $carry, int $item) {
    return $carry + $item;
}, 4);

// 10

Метод reduce также передаёт ключи массива в ассоциативных коллекциях в заданный callback:

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

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

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

// 4264

#reduceSpread() {.collection-method}

Метод reduceSpread сводит коллекцию к массиву значений, передавая результаты каждой итерации в следующую. Этот метод похож на reduce, но может принимать несколько начальных значений:

[$creditsRemaining, $batch] = Image::where('status', 'unprocessed')
    ->get()
    ->reduceSpread(function (int $creditsRemaining, Collection $batch, Image $image) {
        if ($creditsRemaining >= $image->creditsRequired()) {
            $batch->push($image);

            $creditsRemaining -= $image->creditsRequired();
        }

        return [$creditsRemaining, $batch];
    }, $creditsAvailable, collect());

#reject() {.collection-method}

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

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

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

$filtered->all();

// [1, 2]

Для противоположного поведения методу reject используйте метод filter.

#replace() {.collection-method}

Метод replace ведёт себя аналогично merge; однако, помимо перезаписи совпадающих элементов со строковыми ключами, метод replace также перезапишет элементы в коллекции с совпадающими числовыми ключами:

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

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

$replaced->all();

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

#replaceRecursive() {.collection-method}

Этот метод работает как replace, но рекурсивно обрабатывает вложенные массивы, применяя тот же процесс замены к внутренним значениям:

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

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

$replaced->all();

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

#reverse() {.collection-method}

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

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

$reversed = $collection->reverse();

$reversed->all();

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

#search() {.collection-method}

Метод search ищет в коллекции заданное значение и возвращает его ключ, если элемент найден. Если элемент не найден, возвращается false:

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

$collection->search(4);

// 1

Поиск выполняется с использованием "нестрогого" сравнения, то есть строка с числовым значением будет считаться равной числу с тем же значением. Для "строгого" сравнения передайте true вторым аргументом:

collect([2, 4, 6, 8])->search('4', $strict = true);

// false

В качестве альтернативы вы можете передать своё замыкание для поиска первого элемента, который проходит заданное логическое условие:

collect([2, 4, 6, 8])->search(function (int $item, int $key) {
    return $item > 5;
});

// 2

#select() {.collection-method}

Метод select выбирает заданные ключи из коллекции, аналогично SQL-запросу SELECT:

$users = collect([
    ['name' => 'Taylor Otwell', 'role' => 'Developer', 'status' => 'active'],
    ['name' => 'Victoria Faith', 'role' => 'Researcher', 'status' => 'active'],
]);

$users->select(['name', 'role']);

/*
    [
        ['name' => 'Taylor Otwell', 'role' => 'Developer'],
        ['name' => 'Victoria Faith', 'role' => 'Researcher'],
    ],
*/

#shift() {.collection-method}

Метод shift удаляет и возвращает первый элемент коллекции:

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

$collection->shift();

// 1

$collection->all();

// [2, 3, 4, 5]

Вы можете передать целое число в метод shift, чтобы удалить и вернуть несколько элементов с начала коллекции:

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

$collection->shift(3);

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

$collection->all();

// [4, 5]

#shuffle() {.collection-method}

Метод shuffle случайным образом перемешивает элементы коллекции:

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

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (сгенерировано случайно)

#skip() {.collection-method}

Метод skip возвращает новую коллекцию, в которой удалено заданное количество элементов с начала:

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

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

$collection->all();

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

#skipUntil() {.collection-method}

Метод skipUntil пропускает элементы коллекции, пока заданное замыкание не вернёт true, после чего возвращает оставшиеся элементы в виде новой коллекции:

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

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

$subset->all();

// [3, 4]

Вы также можете передать простое значение в метод skipUntil, чтобы пропустить все элементы до тех пор, пока не встретится это значение:

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

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

$subset->all();

// [3, 4]
Внимание

Если заданное значение не найдено или замыкание никогда не возвращает true, метод skipUntil вернёт пустую коллекцию.

#skipWhile() {.collection-method}

Метод skipWhile пропускает элементы коллекции, пока заданное замыкание возвращает true, после чего возвращает оставшиеся элементы в виде новой коллекции:

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

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

$subset->all();

// [4]
Внимание

Если замыкание никогда не возвращает false, метод skipWhile вернёт пустую коллекцию.

#slice() {.collection-method}

Метод slice возвращает срез коллекции, начиная с указанного индекса:

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

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

$slice->all();

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

Если вы хотите ограничить размер возвращаемого среза, передайте желаемый размер вторым аргументом:

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

$slice->all();

// [5, 6]

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

#sliding() {.collection-method}

Метод sliding возвращает новую коллекцию чанков, представляющих "скользящее окно" элементов коллекции:

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

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

$chunks->toArray();

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

Это особенно полезно в сочетании с методом eachSpread:

$transactions->sliding(2)->eachSpread(function (Collection $previous, Collection $current) {
    $current->total = $previous->total + $current->amount;
});

Вы можете опционально передать второй параметр "step", который определяет расстояние между первым элементом каждого чанка:

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

$chunks = $collection->sliding(3, step: 2);

$chunks->toArray();

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

#sole() {.collection-method}

Метод sole возвращает первый элемент коллекции, который проходит заданное логическое условие, но только если условие совпадает ровно с одним элементом:

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

// 2

Вы также можете передать пару ключ / значение в метод sole, который вернёт первый элемент коллекции, совпадающий с заданной парой, но только если совпадает ровно один элемент:

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

$collection->sole('product', 'Chair');

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

В качестве альтернативы вы можете вызвать метод sole без аргументов, чтобы получить первый элемент коллекции, если в ней только один элемент:

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

$collection->sole();

// ['product' => 'Desk', 'price' => 200]

Если в коллекции нет элементов, которые должен вернуть метод sole, будет выброшено исключение \Illuminate\Collections\ItemNotFoundException. Если таких элементов больше одного, будет выброшено исключение \Illuminate\Collections\MultipleItemsFoundException.

#some() {.collection-method}

Псевдоним для метода contains.

#sort() {.collection-method}

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

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

$sorted = $collection->sort();

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

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

Если вам нужна более сложная сортировка, вы можете передать callback в sort с вашим алгоритмом. Обратитесь к документации PHP по функции uasort, которую метод sort использует внутренне.

Примечание

Если вам нужно отсортировать коллекцию вложенных массивов или объектов, смотрите методы sortBy и sortByDesc.

#sortBy() {.collection-method}

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

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

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

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

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

Метод sortBy принимает флаги сортировки в качестве второго аргумента:

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

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

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

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

В качестве альтернативы вы можете передать своё замыкание, чтобы определить, как сортировать значения коллекции:

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

$sorted = $collection->sortBy(function (array $product, int $key) {
    return count($product['colors']);
});

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

/*
    [
        ['name' => 'Chair', 'colors' => ['Black']],
        ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']],
        ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],
    ]
*/

Если вы хотите сортировать коллекцию по нескольким атрибутам, вы можете передать массив атрибутов, по которым нужно сортировать:

$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy(['name', 'age']);

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

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

При сортировке по нескольким атрибутам и направлениям вы можете передать массив операций сортировки в метод sortBy. Каждая операция должна быть массивом, состоящим из атрибута и направления сортировки:

$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
    ['name', 'asc'],
    ['age', 'desc'],
]);

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

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

При сортировке коллекции по нескольким атрибутам вы также можете передать замыкания, определяющие каждую операцию сортировки:

$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
    fn (array $a, array $b) => $a['name'] <=> $b['name'],
    fn (array $a, array $b) => $b['age'] <=> $a['age'],
]);

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

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

#sortByDesc() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод sortBy, но сортирует коллекцию в обратном порядке.

#sortDesc() {.collection-method}

Этот метод сортирует коллекцию в обратном порядке по сравнению с методом sort:

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

$sorted = $collection->sortDesc();

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

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

В отличие от sort, в метод sortDesc нельзя передать замыкание. Вместо этого используйте метод sort и инвертируйте сравнение.

#sortKeys() {.collection-method}

Метод sortKeys сортирует коллекцию по ключам базового ассоциативного массива:

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

$sorted = $collection->sortKeys();

$sorted->all();

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

#sortKeysDesc() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод sortKeys, но сортирует коллекцию в обратном порядке.

#sortKeysUsing() {.collection-method}

Метод sortKeysUsing сортирует коллекцию по ключам базового ассоциативного массива с использованием callback:

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

$sorted = $collection->sortKeysUsing('strnatcasecmp');

$sorted->all();

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

Callback должен быть функцией сравнения, которая возвращает целое число меньше, равное или больше нуля. Подробнее смотрите документацию PHP по функции uksort, которую метод sortKeysUsing использует внутренне.

#splice() {.collection-method}

Метод splice удаляет и возвращает срез элементов, начиная с указанного индекса:

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

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

$chunk->all();

// [3, 4, 5]

$collection->all();

// [1, 2]

Вы можете передать второй аргумент, чтобы ограничить размер возвращаемой коллекции:

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

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

$chunk->all();

// [3]

$collection->all();

// [1, 2, 4, 5]

Кроме того, вы можете передать третий аргумент с новыми элементами, которые заменят удалённые из коллекции:

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

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

$chunk->all();

// [3]

$collection->all();

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

#split() {.collection-method}

Метод split разбивает коллекцию на заданное количество групп:

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

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

$groups->all();

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

#splitIn() {.collection-method}

Метод splitIn разбивает коллекцию на заданное количество групп, полностью заполняя все группы, кроме последней, которой достаётся остаток:

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

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

$groups->all();

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

#sum() {.collection-method}

Метод sum возвращает сумму всех элементов коллекции:

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

// 15

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

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

$collection->sum('pages');

// 1272

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

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

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

// 6

#take() {.collection-method}

Метод take возвращает новую коллекцию с указанным количеством элементов:

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

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

$chunk->all();

// [0, 1, 2]

Также можно передать отрицательное число, чтобы взять указанное количество элементов с конца коллекции:

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

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

$chunk->all();

// [4, 5]

#takeUntil() {.collection-method}

Метод takeUntil возвращает элементы коллекции до тех пор, пока переданный callback не вернёт true:

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

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

$subset->all();

// [1, 2]

Также можно передать простое значение в метод takeUntil, чтобы получить элементы до тех пор, пока не встретится это значение:

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

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

$subset->all();

// [1, 2]
Внимание

Если заданное значение не найдено или callback никогда не возвращает true, метод takeUntil вернёт все элементы коллекции.

#takeWhile() {.collection-method}

Метод takeWhile возвращает элементы коллекции до тех пор, пока переданный callback не вернёт false:

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

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

$subset->all();

// [1, 2]
Внимание

Если callback никогда не возвращает false, метод takeWhile вернёт все элементы коллекции.

#tap() {.collection-method}

Метод tap передаёт коллекцию в указанный callback, позволяя "заглянуть" в коллекцию в определённый момент и выполнить действия с элементами, не изменяя саму коллекцию. Затем метод tap возвращает коллекцию:

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

// 1

#times() {.collection-method}

Статический метод times создаёт новую коллекцию, вызывая переданное замыкание заданное количество раз:

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

$collection->all();

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

#toArray() {.collection-method}

Метод toArray преобразует коллекцию в обычный PHP array. Если значения коллекции — модели Eloquent, они также будут преобразованы в массивы:

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

$collection->toArray();

/*
    [
        ['name' => 'Desk', 'price' => 200],
    ]
*/
Внимание

Метод toArray также преобразует все вложенные объекты коллекции, реализующие интерфейс Arrayable, в массивы. Если вам нужен исходный массив, лежащий в основе коллекции, используйте метод all.

#toJson() {.collection-method}

Метод toJson преобразует коллекцию в JSON-строку:

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

$collection->toJson();

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

#transform() {.collection-method}

Метод transform перебирает коллекцию и вызывает переданный callback для каждого элемента. Элементы коллекции будут заменены значениями, возвращёнными callback:

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

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

$collection->all();

// [2, 4, 6, 8, 10]
Внимание

В отличие от большинства методов коллекций, transform изменяет саму коллекцию. Если вы хотите создать новую коллекцию, используйте метод map.

#undot() {.collection-method}

Метод undot разворачивает одномерную коллекцию с использованием "dot" нотации в многомерную коллекцию:

$person = collect([
    'name.first_name' => 'Marie',
    'name.last_name' => 'Valentine',
    'address.line_1' => '2992 Eagle Drive',
    'address.line_2' => '',
    'address.suburb' => 'Detroit',
    'address.state' => 'MI',
    'address.postcode' => '48219'
]);

$person = $person->undot();

$person->toArray();

/*
    [
        "name" => [
            "first_name" => "Marie",
            "last_name" => "Valentine",
        ],
        "address" => [
            "line_1" => "2992 Eagle Drive",
            "line_2" => "",
            "suburb" => "Detroit",
            "state" => "MI",
            "postcode" => "48219",
        ],
    ]
*/

#union() {.collection-method}

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

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

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

$union->all();

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

#unique() {.collection-method}

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

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

$unique = $collection->unique();

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

// [1, 2, 3, 4]

При работе с вложенными массивами или объектами можно указать ключ, по которому определяется уникальность:

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

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

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

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

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

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

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

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

Метод unique использует "нестрогие" сравнения при проверке значений элементов, то есть строка с числовым значением будет считаться равной целому числу с тем же значением. Для фильтрации с использованием "строгих" сравнений используйте метод uniqueStrict.

Примечание

Поведение этого метода изменяется при использовании Eloquent Collections.

#uniqueStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод unique, но все значения сравниваются с использованием "строгих" сравнений.

#unless() {.collection-method}

Метод unless выполнит переданный колбэк, если первый аргумент метода не приводится к true:

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

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

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

$collection->all();

// [1, 2, 3, 5]

Во второй аргумент метода unless можно передать второй колбэк. Этот колбэк будет выполнен, когда первый аргумент, переданный в unless, оценится как true:

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

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

$collection->all();

// [1, 2, 3, 5]

Для противоположного поведения метода unless смотрите метод when.

#unlessEmpty() {.collection-method}

Псевдоним для метода whenNotEmpty.

#unlessNotEmpty() {.collection-method}

Псевдоним для метода whenEmpty.

#unwrap() {.collection-method}

Статический метод unwrap возвращает внутренние элементы коллекции из переданного значения, если это применимо:

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

// ['John Doe']

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

// ['John Doe']

Collection::unwrap('John Doe');

// 'John Doe'

#value() {.collection-method}

Метод value извлекает заданное значение из первого элемента коллекции:

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

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

// 200

#values() {.collection-method}

Метод values возвращает новую коллекцию с ключами, сброшенными к последовательным целочисленным индексам:

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

$values = $collection->values();

$values->all();

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

#when() {.collection-method}

Метод when выполнит переданный колбэк, когда первый аргумент, переданный в метод, будет оценён как true. Экземпляр коллекции и первый аргумент, переданный в when, будут переданы в замыкание:

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

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

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

$collection->all();

// [1, 2, 3, 4]

В метод when можно передать второй колбэк. Этот колбэк будет выполнен, когда первый аргумент, переданный в when, оценится как false:

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

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

$collection->all();

// [1, 2, 3, 5]

Для противоположного поведения метода when смотрите метод unless.

#whenEmpty() {.collection-method}

Метод whenEmpty выполнит переданный callback, если коллекция пуста:

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// ['Michael', 'Tom']

$collection = collect();

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
});

$collection->all();

// ['Adam']

Во второй аргумент метода whenEmpty можно передать замыкание, которое выполнится, если коллекция не пуста:

$collection = collect(['Michael', 'Tom']);

$collection->whenEmpty(function (Collection $collection) {
    return $collection->push('Adam');
}, function (Collection $collection) {
    return $collection->push('Taylor');
});

$collection->all();

// ['Michael', 'Tom', 'Taylor']

Для противоположного поведения метода whenEmpty смотрите метод whenNotEmpty.

#whenNotEmpty() {.collection-method}

Метод whenNotEmpty выполнит переданный callback, если коллекция не пуста:

$collection = collect(['michael', 'tom']);

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

$collection->all();

// ['michael', 'tom', 'adam']

$collection = collect();

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

$collection->all();

// []

Во второй аргумент метода whenNotEmpty можно передать замыкание, которое выполнится, если коллекция пуста:

$collection = collect();

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

$collection->all();

// ['taylor']

Для противоположного поведения метода whenNotEmpty смотрите метод whenEmpty.

#where() {.collection-method}

Метод where фильтрует коллекцию по заданной паре ключ / значение:

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

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

$filtered->all();

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

Метод where использует "нестрогие" сравнения при проверке значений элементов, то есть строка с числовым значением будет считаться равной целому числу с тем же значением. Для фильтрации с использованием "строгих" сравнений используйте метод whereStrict.

Опционально можно передать оператор сравнения вторым параметром. Поддерживаемые операторы: '===', '!==', '!=', '==', '=', '<>', '>', '<', '>=', и '<=':

$collection = collect([
    ['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
    ['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
    ['name' => 'Sue', 'deleted_at' => null],
]);

$filtered = $collection->where('deleted_at', '!=', null);

$filtered->all();

/*
    [
        ['name' => 'Jim', 'deleted_at' => '2019-01-01 00:00:00'],
        ['name' => 'Sally', 'deleted_at' => '2019-01-02 00:00:00'],
    ]
*/

#whereStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод where, но все значения сравниваются с использованием "строгих" сравнений.

#whereBetween() {.collection-method}

Метод whereBetween фильтрует коллекцию, проверяя, находится ли значение элемента в заданном диапазоне:

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

$filtered = $collection->whereBetween('price', [100, 200]);

$filtered->all();

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

#whereIn() {.collection-method}

Метод whereIn удаляет из коллекции элементы, у которых значение по заданному ключу отсутствует в переданном массиве:

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

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

$filtered->all();

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

Метод whereIn использует "нестрогие" сравнения при проверке значений элементов, то есть строка с числовым значением будет считаться равной целому числу с тем же значением. Для фильтрации с использованием "строгих" сравнений используйте метод whereInStrict.

#whereInStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод whereIn, но все значения сравниваются с использованием "строгих" сравнений.

#whereInstanceOf() {.collection-method}

Метод whereInstanceOf фильтрует коллекцию по заданному типу класса:

use App\Models\User;
use App\Models\Post;

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

$filtered = $collection->whereInstanceOf(User::class);

$filtered->all();

// [App\Models\User, App\Models\User]

#whereNotBetween() {.collection-method}

Метод whereNotBetween фильтрует коллекцию, проверяя, находится ли значение элемента вне заданного диапазона:

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

$filtered = $collection->whereNotBetween('price', [100, 200]);

$filtered->all();

/*
    [
        ['product' => 'Chair', 'price' => 80],
        ['product' => 'Pencil', 'price' => 30],
    ]
*/

#whereNotIn() {.collection-method}

Метод whereNotIn удаляет из коллекции элементы, у которых значение по заданному ключу содержится в переданном массиве:

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

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

$filtered->all();

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

Метод whereNotIn использует "нестрогие" сравнения при проверке значений элементов, то есть строка с числовым значением будет считаться равной целому числу с тем же значением. Для фильтрации с использованием "строгих" сравнений используйте метод whereNotInStrict.

#whereNotInStrict() {.collection-method}

Этот метод имеет ту же сигнатуру, что и метод whereNotIn, но все значения сравниваются с использованием "строгих" сравнений.

#whereNotNull() {.collection-method}

Метод whereNotNull возвращает элементы коллекции, у которых значение по заданному ключу не равно null:

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

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

$filtered->all();

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

#whereNull() {.collection-method}

Метод whereNull возвращает элементы коллекции, у которых значение по заданному ключу равно null:

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

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

$filtered->all();

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

#wrap() {.collection-method}

Статический метод wrap оборачивает переданное значение в коллекцию, если это применимо:

use Illuminate\Support\Collection;

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

$collection->all();

// ['John Doe']

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

$collection->all();

// ['John Doe']

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

$collection->all();

// ['John Doe']

#zip() {.collection-method}

Метод zip объединяет значения переданного массива с соответствующими значениями исходной коллекции по индексам:

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

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

$zipped->all();

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

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

Коллекции также поддерживают "higher order messages" — сокращения для выполнения распространённых действий над коллекциями. Методы коллекций, предоставляющие higher order messages: average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, и unique.

Каждое higher order message можно вызвать как динамическое свойство экземпляра коллекции. Например, используем higher order message each, чтобы вызвать метод у каждого объекта в коллекции:

use App\Models\User;

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

$users->each->markAsVip();

Аналогично, можно использовать higher order message sum, чтобы получить общее количество "голосов" для коллекции пользователей:

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

return $users->sum->votes;

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

#Введение

Внимание

Перед тем как изучать ленивые коллекции Laravel, рекомендуется ознакомиться с PHP генераторами.

В дополнение к уже мощному классу Collection, класс LazyCollection использует PHP генераторы, позволяя работать с очень большими наборами данных при низком потреблении памяти.

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

use App\Models\LogEntry;
use Illuminate\Support\LazyCollection;

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

    while (($line = fgets($handle)) !== false) {
        yield $line;
    }
})->chunk(4)->map(function (array $lines) {
    return LogEntry::fromLines($lines);
})->each(function (LogEntry $logEntry) {
    // Обработать запись лога...
});

Или представьте, что вам нужно перебрать 10 000 моделей Eloquent. При использовании традиционных коллекций Laravel все 10 000 моделей должны быть загружены в память одновременно:

use App\Models\User;

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

Однако метод cursor конструктора запросов возвращает экземпляр LazyCollection. Это позволяет выполнить всего один запрос к базе данных, но при этом в памяти одновременно будет загружена только одна модель Eloquent. В этом примере callback filter не выполняется до тех пор, пока мы не начнём итерировать пользователей по одному, что значительно снижает использование памяти:

use App\Models\User;

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

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

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

Чтобы создать экземпляр ленивой коллекции, нужно передать PHP-генератор в метод make коллекции:

use Illuminate\Support\LazyCollection;

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

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

#Контракт Enumerable

Почти все методы, доступные в классе Collection, также доступны в классе LazyCollection. Оба класса реализуют контракт Illuminate\Support\Enumerable, который определяет следующие методы:

<style> .collection-method-list > p { columns: 10.8em 3; -moz-columns: 10.8em 3; -webkit-columns: 10.8em 3; } .collection-method-list a { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } </style>
Внимание

Методы, изменяющие коллекцию (например, shift, pop, prepend и т.п.), не доступны в классе LazyCollection.

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

Помимо методов, определённых в контракте Enumerable, класс LazyCollection содержит следующие методы:

#takeUntilTimeout() {.collection-method}

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

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

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

    sleep(1);
});

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

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

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

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

#tapEach() {.collection-method}

В то время как метод each сразу вызывает переданный callback для каждого элемента коллекции, метод tapEach вызывает callback только по мере того, как элементы извлекаются из списка по одному:

// Пока ничего не выведено...
$lazyCollection = LazyCollection::times(INF)->tapEach(function (int $value) {
    dump($value);
});

// Выведено три элемента...
$array = $lazyCollection->take(3)->all();

// 1
// 2
// 3

#remember() {.collection-method}

Метод remember возвращает новую ленивую коллекцию, которая запоминает уже перечисленные значения и не извлекает их повторно при последующих перечислениях коллекции:

// Запрос ещё не выполнен...
$users = User::cursor()->remember();

// Запрос выполняется...
// Первые 5 пользователей загружаются из базы данных...
$users->take(5)->all();

// Первые 5 пользователей берутся из кеша коллекции...
// Остальные загружаются из базы данных...
$users->take(20)->all();