Коллекции
Введение
Класс Illuminate\Support\Collection
предоставляет плавную и удобную оболочку для работы с массивами данных. Например, посмотрите следующий код. Мы воспользуемся помощником collect
для создания нового экземпляра коллекции из массива, запустим функцию strtoupper
для каждого элемента, а затем удалим все пустые элементы:
$collection = collect(['taylor', 'abigail', null])->map(function ($name) { return strtoupper($name);})->reject(function ($name) { return empty($name);});
Как видите, класс Collection
позволяет вам объединять свои методы в цепочку для выполнения плавного сопоставления и сокращения базового массива. В общем, коллекции неизменяемы, что означает, что каждый метод Collection
возвращает совершенно новый экземпляр Collection
.
Создание коллекций
Как упоминалось выше, помощник collect
возвращает новый экземпляр Illuminate\Support\Collection
для данного массива. Итак, создать коллекцию очень просто:
$collection = collect([1, 2, 3]);
{tip} Результаты запросов Eloquent всегда возвращаются как экземпляры
Collection
.
Расширение коллекций
Коллекции являются «макросъемочными», что позволяет вам добавлять дополнительные методы к классу Collection
во время выполнения. Метод macro
класса Illuminate\Support\Collection
принимает замыкание, которое будет выполнено при вызове вашего макроса. Замыкание макроса может получить доступ к другим методам коллекции через $this
, как если бы это был реальный метод класса коллекции. Например, следующий код добавляет метод toUpper
к классу Collection
:
use Illuminate\Support\Collection;use Illuminate\Support\Str; Collection::macro('toUpper', function () { return $this->map(function ($value) { return Str::upper($value); });}); $collection = collect(['first', 'second']); $upper = $collection->toUpper(); // ['FIRST', 'SECOND']
Как правило, вы должны объявлять макросы сбора в методе boot
сервис провайдера.
Макро-аргументы
При необходимости вы можете определить макросы, которые принимают дополнительные аргументы:
use Illuminate\Support\Collection;use Illuminate\Support\Facades\Lang; Collection::macro('toLocale', function ($locale) { return $this->map(function ($value) use ($locale) { return Lang::get($value, [], $locale); });}); $collection = collect(['first', 'second']); $translated = $collection->toLocale('es');
Доступные методы
Для большей части оставшейся документации по коллекциям мы обсудим каждый метод, доступный в классе Collection
. Помните, что все эти методы могут быть объединены в цепочку для беспрепятственного управления базовым массивом. Более того, почти каждый метод возвращает новый экземпляр Collection
, позволяя вам при необходимости сохранить исходную копию коллекции:
all average avg chunk chunkWhile collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys doesntContain dump duplicates duplicatesStrict each eachSpread every except filter first firstWhere flatMap flatten flip forget forPage get groupBy has implode intersect intersectByKeys isEmpty isNotEmpty join keyBy keys last macro make map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode nth only pad partition pipe pipeInto pipeThrough pluck pop prepend pull push put random range reduce reduceSpread reject replace replaceRecursive reverse search shift shuffle sliding skip skipUntil skipWhile slice sole some sort sortBy sortByDesc sortDesc sortKeys sortKeysDesc sortKeysUsing splice split splitIn sum take takeUntil takeWhile tap times toArray toJson transform undot union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict whereNotNull whereNull wrap zip
Method Listing
all()
Метод all
возвращает базовый массив, представленный коллекцией:
collect([1, 2, 3])->all(); // [1, 2, 3]
average()
Псевдоним для метода avg
.
avg()
Метод avg
возвращает среднее значение заданного ключа:
$average = collect([ ['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->avg('foo'); // 20 $average = collect([1, 1, 2, 4])->avg(); // 2
chunk()
Метод chunk
разбивает коллекцию на несколько меньших коллекций заданного размера:
$collection = collect([1, 2, 3, 4, 5, 6, 7]); $chunks = $collection->chunk(4); $chunks->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()
Метод chunkWhile
разбивает коллекцию на несколько меньших по размеру коллекций на основе оценки данного обратного вызова. Переменная $chunk
, переданная в замыкание, может использоваться для проверки предыдущего элемента:
$collection = collect(str_split('AABBCCCD')); $chunks = $collection->chunkWhile(function ($value, $key, $chunk) { return $value === $chunk->last();}); $chunks->all(); // [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]
collapse()
Метод collapse
сворачивает коллекцию массивов в единую плоскую коллекцию:
$collection = collect([ [1, 2, 3], [4, 5, 6], [7, 8, 9],]); $collapsed = $collection->collapse(); $collapsed->all(); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
collect()
Метод collect
возвращает новый экземпляр Collection
с элементами, находящимися в настоящее время в коллекции:
$collectionA = collect([1, 2, 3]); $collectionB = $collectionA->collect(); $collectionB->all(); // [1, 2, 3]
Метод collect
в первую очередь полезен для преобразования отложенных коллекций в стандартные экземпляры Collection
:
$lazyCollection = LazyCollection::make(function () { yield 1; yield 2; yield 3;}); $collection = $lazyCollection->collect(); get_class($collection); // 'Illuminate\Support\Collection' $collection->all(); // [1, 2, 3]
{tip} Метод
collect
особенно полезен, когда у вас есть экземплярEnumerable
и вам нужен экземпляр не отложенной коллекции. Посколькуcollect()
является частью контрактаEnumerable
, вы можете безопасно использовать его для получения экземпляраCollection
.
combine()
Метод combine
объединяет значения коллекции в качестве ключей со значениями другого массива или коллекции:
$collection = collect(['name', 'age']); $combined = $collection->combine(['George', 29]); $combined->all(); // ['name' => 'George', 'age' => 29]
concat()
Метод concat
добавляет значения данного массива array
или коллекции в конец другой коллекции:
$collection = collect(['John Doe']); $concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']); $concatenated->all(); // ['John Doe', 'Jane Doe', 'Johnny Doe']
contains()
Метод contains
определяет, содержит ли коллекция данный элемент. Вы можете передать замыкание методу contains
, чтобы определить, существует ли в коллекции элемент, соответствующий заданному критерию истинности:
$collection = collect([1, 2, 3, 4, 5]); $collection->contains(function ($value, $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
для фильтрации с использованием «строгих» сравнений.
For the inverse of contains
, see the doesntContain method.
containsStrict()
Этот метод имеет ту же сигнатуру, что и метод contains
; однако все значения сравниваются с использованием «строгих» сравнений.
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
count()
Метод count
возвращает общее количество элементов в коллекции:
$collection = collect([1, 2, 3, 4]); $collection->count(); // 4
countBy()
Метод countBy
подсчитывает вхождения значений в коллекцию. По умолчанию метод подсчитывает вхождения каждого элемента, что позволяет вам подсчитывать определенные «типы» элементов в коллекции:
$collection = collect([1, 2, 2, 2, 3]); $counted = $collection->countBy(); $counted->all(); // [1 => 1, 2 => 3, 3 => 1]
Вы передаете замыкание методу countBy
для подсчета всех элементов по заданному значению:
$collection = collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']); $counted = $collection->countBy(function ($email) { return substr(strrchr($email, "@"), 1);}); $counted->all(); // ['gmail.com' => 2, 'yahoo.com' => 1]
crossJoin()
Метод crossJoin
объединяет значения коллекции среди заданных массивов или коллекций, возвращая декартово произведение со всеми возможными перестановками:
$collection = collect([1, 2]); $matrix = $collection->crossJoin(['a', 'b']); $matrix->all(); /* [ [1, 'a'], [1, 'b'], [2, 'a'], [2, 'b'], ]*/ $collection = collect([1, 2]); $matrix = $collection->crossJoin(['a', 'b'], ['I', 'II']); $matrix->all(); /* [ [1, 'a', 'I'], [1, 'a', 'II'], [1, 'b', 'I'], [1, 'b', 'II'], [2, 'a', 'I'], [2, 'a', 'II'], [2, 'b', 'I'], [2, 'b', 'II'], ]*/
dd()
Метод dd
выгружает элементы коллекции и завершает выполнение скрипта:
$collection = collect(['John Doe', 'Jane Doe']); $collection->dd(); /* Collection { #items: array:2 [ 0 => "John Doe" 1 => "Jane Doe" ] }*/
Если вы не хотите останавливать выполнение сценария, используйте вместо него метод dump
.
diff()
Метод diff
сравнивает коллекцию с другой коллекцией или простым массивом PHP array
на основе его значений. Этот метод вернет значения в исходной коллекции, которых нет в данной коллекции:
$collection = collect([1, 2, 3, 4, 5]); $diff = $collection->diff([2, 4, 6, 8]); $diff->all(); // [1, 3, 5]
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
diffAssoc()
Метод diffAssoc
сравнивает коллекцию с другой коллекцией или простым массивом PHP array
на основе его ключей и значений. Этот метод вернет пары ключ / значение в исходной коллекции, которых нет в данной коллекции:
$collection = collect([ 'color' => 'orange', 'type' => 'fruit', 'remain' => 6,]); $diff = $collection->diffAssoc([ 'color' => 'yellow', 'type' => 'fruit', 'remain' => 3, 'used' => 6,]); $diff->all(); // ['color' => 'orange', 'remain' => 6]
diffKeys()
Метод 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()
The doesntContain
method determines whether the collection does not contain a given item. You may pass a closure to the doesntContain
method to determine if an element does not exist in the collection matching a given truth test:
$collection = collect([1, 2, 3, 4, 5]); $collection->doesntContain(function ($value, $key) { return $value < 5;}); // false
Alternatively, you may pass a string to the doesntContain
method to determine whether the collection does not contain a given item value:
$collection = collect(['name' => 'Desk', 'price' => 100]); $collection->doesntContain('Table'); // true $collection->doesntContain('Desk'); // false
You may also pass a key / value pair to the doesntContain
method, which will determine if the given pair does not exist in the collection:
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100],]); $collection->doesntContain('product', 'Bookcase'); // true
The doesntContain
method uses "loose" comparisons when checking item values, meaning a string with an integer value will be considered equal to an integer of the same value.
dump()
Метод dump
выгружает элементы коллекции:
$collection = collect(['John Doe', 'Jane Doe']); $collection->dump(); /* Collection { #items: array:2 [ 0 => "John Doe" 1 => "Jane Doe" ] }*/
Если вы хотите остановить выполнение сценария после сброса коллекции, используйте вместо него метод dd
.
duplicates()
Метод 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()
Этот метод имеет ту же сигнатуру, что и метод duplicates
; однако все значения сравниваются с использованием «строгих» сравнений.
each()
Метод each
выполняет итерацию по элементам в коллекции и передает каждый элемент в замыкание:
$collection->each(function ($item, $key) { //});
Если вы хотите прекратить итерацию по элементам, вы можете вернуть false
из вашего замыкания:
$collection->each(function ($item, $key) { if (/* condition */) { return false; }});
eachSpread()
Метод eachSpread
выполняет итерацию по элементам коллекции, передавая значение каждого вложенного элемента в заданный обратный вызов:
$collection = collect([['John Doe', 35], ['Jane Doe', 33]]); $collection->eachSpread(function ($name, $age) { //});
Вы можете прекратить итерацию по элементам, вернув false
из обратного вызова:
$collection->eachSpread(function ($name, $age) { return false;});
every()
Метод every
может использоваться для проверки того, что все элементы коллекции проходят заданный тест истинности:
collect([1, 2, 3, 4])->every(function ($value, $key) { return $value > 2;}); // false
Если коллекция пуста, метод every
вернет true
:
$collection = collect([]); $collection->every(function ($value, $key) { return $value > 2;}); // true
except()
Метод except
возвращает все элементы в коллекции, кроме тех, которые имеют указанные ключи:
$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]); $filtered = $collection->except(['price', 'discount']); $filtered->all(); // ['product_id' => 1]
Чтобы узнать об обратном к except
, смотрите метод only.
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
filter()
Метод filter
фильтрует коллекцию с помощью заданного обратного вызова, сохраняя только те элементы, которые проходят заданный тест на истинность:
$collection = collect([1, 2, 3, 4]); $filtered = $collection->filter(function ($value, $key) { return $value > 2;}); $filtered->all(); // [3, 4]
Если обратный вызов не предоставлен, все записи коллекции, эквивалентные false
, будут удалены:
$collection = collect([1, 2, 3, null, false, '', 0, []]); $collection->filter()->all(); // [1, 2, 3]
Для обратного к filter
, смотрите метод reject.
first()
Метод first
возвращает первый элемент в коллекции, который проходит заданную проверку истинности:
collect([1, 2, 3, 4])->first(function ($value, $key) { return $value > 2;}); // 3
Вы также можете вызвать метод first
без аргументов, чтобы получить первый элемент в коллекции. Если коллекция пуста, возвращается null
:
collect([1, 2, 3, 4])->first(); // 1
firstWhere()
Метод firstWhere
возвращает первый элемент коллекции с заданной парой ключ / значение:
$collection = collect([ ['name' => 'Regena', 'age' => 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()
Метод flatMap
выполняет итерацию по коллекции и передает каждое значение заданному замыканию. Замыкание может изменить элемент и вернуть его, таким образом формируя новую коллекцию измененных элементов. Затем массив выравнивается на один уровень:
$collection = collect([ ['name' => 'Sally'], ['school' => 'Arkansas'], ['age' => 28]]); $flattened = $collection->flatMap(function ($values) { return array_map('strtoupper', $values);}); $flattened->all(); // ['name' => 'SALLY', 'school' => 'ARKANSAS', 'age' => '28'];
flatten()
Метод flatten
сводит многомерную коллекцию в одно измерение:
$collection = collect([ 'name' => 'taylor', 'languages' => [ 'php', 'javascript' ]]); $flattened = $collection->flatten(); $flattened->all(); // ['taylor', 'php', 'javascript'];
При необходимости вы можете передать методу 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()
Метод flip
меняет местами ключи коллекции на их соответствующие значения:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $flipped = $collection->flip(); $flipped->all(); // ['taylor' => 'name', 'laravel' => 'framework']
forget()
Метод forget
удаляет элемент из коллекции по его ключу:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $collection->forget('name'); $collection->all(); // ['framework' => 'laravel']
{note} В отличие от большинства других методов сбора,
forget
не возвращает новую измененную коллекцию; он изменяет вызываемую коллекцию.
forPage()
Метод forPage
возвращает новую коллекцию, содержащую элементы, которые будут присутствовать на заданном номере страницы. Метод принимает номер страницы в качестве первого аргумента и количество элементов, отображаемых на странице, в качестве второго аргумента:
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]); $chunk = $collection->forPage(2, 3); $chunk->all(); // [4, 5, 6]
get()
Метод get
возвращает элемент по заданному ключу. Если ключ не существует, возвращается null
:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $value = $collection->get('name'); // taylor
При желании вы можете передать значение по умолчанию в качестве второго аргумента:
$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $value = $collection->get('age', 34); // 34
Вы даже можете передать обратный вызов в качестве значения метода по умолчанию. Результат обратного вызова будет возвращен, если указанный ключ не существует:
$collection->get('email', function () { return 'taylor@example.com';}); // taylor@example.com
groupBy()
Метод groupBy
группирует элементы коллекции по заданному ключу:
$collection = collect([ ['account_id' => 'account-x10', 'product' => 'Chair'], ['account_id' => 'account-x10', 'product' => 'Bookcase'], ['account_id' => 'account-x11', 'product' => 'Desk'],]); $grouped = $collection->groupBy('account_id'); $grouped->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 ($item, $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 ($item) { return $item['roles'];}], $preserveKeys = true); /*[ 1 => [ 'Role_1' => [ 10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']], 20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']], ], 'Role_2' => [ 20 => ['user' => 2, 'skill' => 1, 'roles' => ['Role_1', 'Role_2']], ], 'Role_3' => [ 10 => ['user' => 1, 'skill' => 1, 'roles' => ['Role_1', 'Role_3']], ], ], 2 => [ 'Role_1' => [ 30 => ['user' => 3, 'skill' => 2, 'roles' => ['Role_1']], ], 'Role_2' => [ 40 => ['user' => 4, 'skill' => 2, 'roles' => ['Role_2']], ], ],];*/
has()
Метод has
определяет, существует ли данный ключ в коллекции:
$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]); $collection->has('product'); // true $collection->has(['product', 'amount']); // true $collection->has(['amount', 'price']); // false
implode()
Метод implode
объединяет элементы в коллекцию. Его аргументы зависят от типа элементов в коллекции. Если коллекция содержит массивы или объекты, вы должны передать ключ атрибутов, которые вы хотите объединить, и «связующую» строку, которую вы хотите разместить между значениями:
$collection = collect([ ['account_id' => 1, 'product' => 'Desk'], ['account_id' => 2, 'product' => 'Chair'],]); $collection->implode('product', ', '); // Desk, Chair
Если коллекция содержит простые строки или числовые значения, вы должны передать "glue" в качестве единственного аргумента метода:
collect([1, 2, 3, 4, 5])->implode('-'); // '1-2-3-4-5'
intersect()
Метод intersect
удаляет любые значения из исходной коллекции, которых нет в данном array
или коллекции. Полученная коллекция сохранит ключи исходной коллекции:
$collection = collect(['Desk', 'Sofa', 'Chair']); $intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']); $intersect->all(); // [0 => 'Desk', 2 => 'Chair']
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
intersectByKeys()
Метод 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()
Метод isEmpty
возвращает true
, если коллекция пуста; в противном случае возвращается false
:
collect([])->isEmpty(); // true
isNotEmpty()
Метод isNotEmpty
возвращает true
, если коллекция не пуста; в противном случае возвращается false
:
collect([])->isNotEmpty(); // false
join()
Метод 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()
Метод keyBy
передает коллекцию заданным ключом. Если у нескольких элементов один и тот же ключ, в новой коллекции появится только последний:
$collection = collect([ ['product_id' => 'prod-100', 'name' => 'Desk'], ['product_id' => 'prod-200', 'name' => 'Chair'],]); $keyed = $collection->keyBy('product_id'); $keyed->all(); /* [ 'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'], 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'], ]*/
Вы также можете передать методу обратный вызов. Обратный вызов должен возвращать значение для ключа коллекции:
$keyed = $collection->keyBy(function ($item) { return strtoupper($item['product_id']);}); $keyed->all(); /* [ 'PROD-100' => ['product_id' => 'prod-100', 'name' => 'Desk'], 'PROD-200' => ['product_id' => 'prod-200', 'name' => 'Chair'], ]*/
keys()
Метод keys
возвращает все ключи коллекции:
$collection = collect([ 'prod-100' => ['product_id' => 'prod-100', 'name' => 'Desk'], 'prod-200' => ['product_id' => 'prod-200', 'name' => 'Chair'],]); $keys = $collection->keys(); $keys->all(); // ['prod-100', 'prod-200']
last()
Метод last
возвращает последний элемент в коллекции, который проходит заданный тест на истинность:
collect([1, 2, 3, 4])->last(function ($value, $key) { return $value < 3;}); // 2
Вы также можете вызвать метод last
без аргументов, чтобы получить последний элемент в коллекции. Если коллекция пуста, возвращается null
:
collect([1, 2, 3, 4])->last(); // 4
macro()
Статический метод macro
позволяет вам добавлять методы к классу Collection
во время выполнения. Обратитесь к документации по расширению коллекций для получения дополнительной информации.
make()
Статический метод make
создает новый экземпляр коллекции. Смотрите раздел Создание коллекций.
map()
Метод map
выполняет итерацию по коллекции и передает каждое значение в заданный обратный вызов. Обратный вызов может изменять элемент и возвращать его, тем самым формируя новую коллекцию измененных элементов:
$collection = collect([1, 2, 3, 4, 5]); $multiplied = $collection->map(function ($item, $key) { return $item * 2;}); $multiplied->all(); // [2, 4, 6, 8, 10]
{note} Как и большинство других методов коллекции,
map
возвращает новый экземпляр коллекции; он не изменяет вызываемую коллекцию. Если вы хотите преобразовать исходную коллекцию, используйте методtransform
method.
mapInto()
Метод mapInto()
выполняет итерацию по коллекции, создавая новый экземпляр данного класса, передавая значение в конструктор:
class Currency{ /** * Create a new currency instance. * * @param string $code * @return void */ function __construct(string $code) { $this->code = $code; }} $collection = collect(['USD', 'EUR', 'GBP']); $currencies = $collection->mapInto(Currency::class); $currencies->all(); // [Currency('USD'), Currency('EUR'), Currency('GBP')]
mapSpread()
Метод mapSpread
выполняет итерацию по элементам коллекции, передавая значение каждого вложенного элемента в заданное замыкание. Замыкание может изменить элемент и вернуть его, таким образом формируя новую коллекцию измененных элементов:
$collection = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); $chunks = $collection->chunk(2); $sequence = $chunks->mapSpread(function ($even, $odd) { return $even + $odd;}); $sequence->all(); // [1, 5, 9, 13, 17]
mapToGroups()
Метод mapToGroups
группирует элементы коллекции по заданному замыканию. Замыкание должно возвращать ассоциативный массив, содержащий одну пару ключ / значение, таким образом формируя новую коллекцию сгруппированных значений:
$collection = collect([ [ 'name' => 'John Doe', 'department' => 'Sales', ], [ 'name' => 'Jane Doe', 'department' => 'Sales', ], [ 'name' => 'Johnny Doe', 'department' => 'Marketing', ]]); $grouped = $collection->mapToGroups(function ($item, $key) { return [$item['department'] => $item['name']];}); $grouped->all(); /* [ 'Sales' => ['John Doe', 'Jane Doe'], 'Marketing' => ['Johnny Doe'], ]*/ $grouped->get('Sales')->all(); // ['John Doe', 'Jane Doe']
mapWithKeys()
Метод mapWithKeys
выполняет итерацию по коллекции и передает каждое значение в заданный обратный вызов. Обратный вызов должен возвращать ассоциативный массив, содержащий одну пару ключ / значение:
$collection = collect([ [ 'name' => 'John', 'department' => 'Sales', 'email' => 'john@example.com', ], [ 'name' => 'Jane', 'department' => 'Marketing', 'email' => 'jane@example.com', ]]); $keyed = $collection->mapWithKeys(function ($item, $key) { return [$item['email'] => $item['name']];}); $keyed->all(); /* [ 'john@example.com' => 'John', 'jane@example.com' => 'Jane', ]*/
max()
Метод max
возвращает максимальное значение данного ключа:
$max = collect([ ['foo' => 10], ['foo' => 20]])->max('foo'); // 20 $max = collect([1, 2, 3, 4, 5])->max(); // 5
median()
Метод median
возвращает среднее значение заданного ключа:
$median = collect([ ['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->median('foo'); // 15 $median = collect([1, 1, 2, 4])->median(); // 1.5
merge()
Метод merge
объединяет данный массив или коллекцию с исходной коллекцией. Если строковый ключ в данных элементах совпадает со строковым ключом в исходной коллекции, значение данного элемента перезапишет значение в исходной коллекции:
$collection = collect(['product_id' => 1, 'price' => 100]); $merged = $collection->merge(['price' => 200, 'discount' => false]); $merged->all(); // ['product_id' => 1, 'price' => 200, 'discount' => false]
Если ключи данных элементов являются числовыми, значения будут добавлены в конец коллекции:
$collection = collect(['Desk', 'Chair']); $merged = $collection->merge(['Bookcase', 'Door']); $merged->all(); // ['Desk', 'Chair', 'Bookcase', 'Door']
mergeRecursive()
Метод 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()
Метод min
возвращает минимальное значение данного ключа:
$min = collect([['foo' => 10], ['foo' => 20]])->min('foo'); // 10 $min = collect([1, 2, 3, 4, 5])->min(); // 1
mode()
Метод mode
возвращает среднюю величину заданного ключа:
$mode = collect([ ['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40]])->mode('foo'); // [10] $mode = collect([1, 1, 2, 4])->mode(); // [1] $mode = collect([1, 1, 2, 2])->mode(); // [1, 2]
nth()
Метод nth
создает новую коллекцию, состоящую из каждого n-го элемента:
$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']); $collection->nth(4); // ['a', 'e']
При желании вы можете передать начальное смещение в качестве второго аргумента:
$collection->nth(4, 1); // ['b', 'f']
only()
Метод only
возвращает элементы в коллекции с указанными ключами:
$collection = collect([ 'product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]); $filtered = $collection->only(['product_id', 'name']); $filtered->all(); // ['product_id' => 1, 'name' => 'Desk']
Чтобы узнать об обратном к only
, смотрите метод except.
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
pad()
Метод pad
будет заполнять массив заданным значением, пока массив не достигнет заданного размера. Этот метод ведет себя как PHP функция array_pad.
Для прокладки влево следует указать отрицательный размер. Заполнение не произойдет, если абсолютное значение данного размера меньше или равно длине массива:
$collection = collect(['A', 'B', 'C']); $filtered = $collection->pad(5, 0); $filtered->all(); // ['A', 'B', 'C', 0, 0] $filtered = $collection->pad(-5, 0); $filtered->all(); // [0, 0, 'A', 'B', 'C']
partition()
Метод partition
может быть объединен с деструктуризацией массива PHP, чтобы отделить элементы, которые проходят данную проверку истинности, от тех, которые не проходят:
$collection = collect([1, 2, 3, 4, 5, 6]); [$underThree, $equalOrAboveThree] = $collection->partition(function ($i) { return $i < 3;}); $underThree->all(); // [1, 2] $equalOrAboveThree->all(); // [3, 4, 5, 6]
pipe()
Метод pipe
передает коллекцию данному замыканию и возвращает результат выполненного замыкания:
$collection = collect([1, 2, 3]); $piped = $collection->pipe(function ($collection) { return $collection->sum();}); // 6
pipeInto()
Метод pipeInto
создает новый экземпляр данного класса и передает коллекцию в конструктор:
class ResourceCollection{ /** * The Collection instance. */ public $collection; /** * Create a new ResourceCollection instance. * * @param Collection $collection * @return void */ public function __construct(Collection $collection) { $this->collection = $collection; }} $collection = collect([1, 2, 3]); $resource = $collection->pipeInto(ResourceCollection::class); $resource->collection->all(); // [1, 2, 3]
pipeThrough()
The pipeThrough
method passes the collection to the given array of closures and returns the result of the executed closures:
$collection = collect([1, 2, 3]); $result = $collection->pipeThrough([ function ($collection) { return $collection->merge([4, 5]); }, function ($collection) { return $collection->sum(); },]); // 15
pluck()
Метод pluck
извлекает все значения для данного ключа:
$collection = collect([ ['product_id' => 'prod-100', 'name' => 'Desk'], ['product_id' => 'prod-200', 'name' => 'Chair'],]); $plucked = $collection->pluck('name'); $plucked->all(); // ['Desk', 'Chair']
Вы также можете указать, как вы хотите, чтобы полученная коллекция была привязана к ключу:
$plucked = $collection->pluck('name', 'product_id'); $plucked->all(); // ['prod-100' => 'Desk', 'prod-200' => 'Chair']
Метод pluck
также поддерживает получение вложенных значений с использованием "точечной" нотации:
$collection = collect([ [ 'speakers' => [ 'first_day' => ['Rosa', 'Judith'], 'second_day' => ['Angela', 'Kathleen'], ], ],]); $plucked = $collection->pluck('speakers.first_day'); $plucked->all(); // ['Rosa', 'Judith']
Если существуют повторяющиеся ключи, последний соответствующий элемент будет вставлен в собранную коллекцию:
$collection = collect([ ['brand' => 'Tesla', 'color' => 'red'], ['brand' => 'Pagani', 'color' => 'white'], ['brand' => 'Tesla', 'color' => 'black'], ['brand' => 'Pagani', 'color' => 'orange'],]); $plucked = $collection->pluck('color', 'brand'); $plucked->all(); // ['Tesla' => 'black', 'Pagani' => 'orange']
pop()
Метод pop
удаляет и возвращает последний элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]); $collection->pop(); // 5 $collection->all(); // [1, 2, 3, 4]
You may pass an integer to the pop
method to remove and return multiple items from the end of a collection:
$collection = collect([1, 2, 3, 4, 5]); $collection->pop(3); // collect([5, 4, 3]) $collection->all(); // [1, 2]
prepend()
Метод prepend
добавляет элемент в начало коллекции:
$collection = collect([1, 2, 3, 4, 5]); $collection->prepend(0); $collection->all(); // [0, 1, 2, 3, 4, 5]
Вы также можете передать второй аргумент, чтобы указать ключ добавляемого элемента:
$collection = collect(['one' => 1, 'two' => 2]); $collection->prepend(0, 'zero'); $collection->all(); // ['zero' => 0, 'one' => 1, 'two' => 2]
pull()
Метод pull
удаляет и возвращает элемент из коллекции по его ключу:
$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']); $collection->pull('name'); // 'Desk' $collection->all(); // ['product_id' => 'prod-100']
push()
Метод push
добавляет элемент в конец коллекции:
$collection = collect([1, 2, 3, 4]); $collection->push(5); $collection->all(); // [1, 2, 3, 4, 5]
put()
Метод put
устанавливает заданный ключ и значение в коллекции:
$collection = collect(['product_id' => 1, 'name' => 'Desk']); $collection->put('price', 100); $collection->all(); // ['product_id' => 1, 'name' => 'Desk', 'price' => 100]
random()
Метод random
возвращает случайный элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]); $collection->random(); // 4 - (retrieved randomly)
Вы можете передать целое число в random
, чтобы указать, сколько элементов вы хотите получить случайным образом. Коллекция элементов всегда возвращается при явной передаче количества элементов, которые вы хотите получить:
$random = $collection->random(3); $random->all(); // [2, 4, 5] - (retrieved randomly)
Если в экземпляре коллекции меньше элементов, чем запрошено, метод random
вызовет исключение InvalidArgumentException
.
range()
The range
method returns a collection containing integers between the specified range:
$collection = collect()->range(3, 6); $collection->all(); // [3, 4, 5, 6]
reduce()
Метод reduce
сокращает коллекцию до одного значения, передавая результат каждой итерации в следующую итерацию:
$collection = collect([1, 2, 3]); $total = $collection->reduce(function ($carry, $item) { return $carry + $item;}); // 6
Значение $carry
на первой итерации равно null
; однако вы можете указать его начальное значение, передав второй аргумент функции reduce
:
$collection->reduce(function ($carry, $item) { return $carry + $item;}, 4); // 10
Метод reduce
также передает ключи массива в ассоциативных коллекциях заданному обратному вызову:
$collection = collect([ 'usd' => 1400, 'gbp' => 1200, 'eur' => 1000,]); $ratio = [ 'usd' => 1, 'gbp' => 1.37, 'eur' => 1.22,]; $collection->reduce(function ($carry, $value, $key) use ($ratio) { return $carry + ($value * $ratio[$key]);}); // 4264
reduceSpread()
The reduceSpread
method reduces the collection to an array of values, passing the results of each iteration into the subsequent iteration. This method is similar to the reduce
method; however, it can accept multiple initial values:
[$creditsRemaining, $batch] = Image::where('status', 'unprocessed') ->get() ->reduceSpread(function ($creditsRemaining, $batch, $image) { if ($creditsRemaining >= $image->creditsRequired()) { $batch->push($image); $creditsRemaining -= $image->creditsRequired(); } return [$creditsRemaining, $batch]; }, $creditsAvailable, collect());
reject()
Метод reject
фильтрует коллекцию, используя заданное замыкание. Замыкание должно вернуть true
, если элемент должен быть удален из результирующей коллекции:
$collection = collect([1, 2, 3, 4]); $filtered = $collection->reject(function ($value, $key) { return $value > 2;}); $filtered->all(); // [1, 2]
Обратный к методу reject
, смотрите метод filter
.
replace()
Метод replace
ведет себя аналогично merge
; однако, помимо перезаписи совпадающих элементов, имеющих строковые ключи, метод replace
также перезаписывает элементы в коллекции, у которых есть совпадающие числовые ключи:
$collection = collect(['Taylor', 'Abigail', 'James']); $replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']); $replaced->all(); // ['Taylor', 'Victoria', 'James', 'Finn']
replaceRecursive()
Этот метод работает как replace
, но он будет повторяться в массивах и применять тот же процесс замены к внутренним значениям:
$collection = collect([ 'Taylor', 'Abigail', [ 'James', 'Victoria', 'Finn' ]]); $replaced = $collection->replaceRecursive([ 'Charlie', 2 => [1 => 'King']]); $replaced->all(); // ['Charlie', 'Abigail', ['James', 'King', 'Finn']]
reverse()
Метод reverse
меняет порядок элементов коллекции на обратный, сохраняя исходные ключи:
$collection = collect(['a', 'b', 'c', 'd', 'e']); $reversed = $collection->reverse(); $reversed->all(); /* [ 4 => 'e', 3 => 'd', 2 => 'c', 1 => 'b', 0 => 'a', ]*/
search()
Метод search
ищет в коллекции заданное значение и возвращает его ключ, если он найден. Если элемент не найден, возвращается false
:
$collection = collect([2, 4, 6, 8]); $collection->search(4); // 1
Поиск выполняется с использованием «свободного» сравнения, то есть строка с целым значением будет считаться равной целому числу того же значения. Чтобы использовать «строгое» сравнение, передайте true
в качестве второго аргумента метода:
collect([2, 4, 6, 8])->search('4', $strict = true); // false
В качестве альтернативы вы можете предоставить собственное замыкание для поиска первого элемента, который проходит заданный тест на истинность:
collect([2, 4, 6, 8])->search(function ($item, $key) { return $item > 5;}); // 2
shift()
Метод shift
удаляет и возвращает первый элемент из коллекции:
$collection = collect([1, 2, 3, 4, 5]); $collection->shift(); // 1 $collection->all(); // [2, 3, 4, 5]
You may pass an integer to the shift
method to remove and return multiple items from the beginning of a collection:
$collection = collect([1, 2, 3, 4, 5]); $collection->shift(3); // collect([1, 2, 3]) $collection->all(); // [4, 5]
shuffle()
Метод shuffle
случайным образом перемешивает элементы в коллекции:
$collection = collect([1, 2, 3, 4, 5]); $shuffled = $collection->shuffle(); $shuffled->all(); // [3, 2, 5, 1, 4] - (generated randomly)
sliding()
The sliding
method returns a new collection of chunks representing a "sliding window" view of the items in the collection:
$collection = collect([1, 2, 3, 4, 5]); $chunks = $collection->sliding(2); $chunks->toArray(); // [[1, 2], [2, 3], [3, 4], [4, 5]]
This is especially useful in conjunction with the eachSpread
method:
$transactions->sliding(2)->eachSpread(function ($previous, $current) { $current->total = $previous->total + $current->amount;});
You may optionally pass a second "step" value, which determines the distance between the first item of every chunk:
$collection = collect([1, 2, 3, 4, 5]); $chunks = $collection->sliding(3, step: 2); $chunks->toArray(); // [[1, 2, 3], [3, 4, 5]]
skip()
Метод 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()
Метод skipUntil
пропускает элементы из коллекции до тех пор, пока данный обратный вызов не вернет true
, а затем вернет оставшиеся элементы в коллекции как новый экземпляр коллекции:
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(function ($item) { return $item >= 3;}); $subset->all(); // [3, 4]
Вы также можете передать простое значение методу skipUntil
, чтобы пропустить все элементы, пока не будет найдено заданное значение:
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(3); $subset->all(); // [3, 4]
{note} Если данное значение не найдено или обратный вызов никогда не возвращает
true
, методskipUntil
вернет пустую коллекцию.
skipWhile()
Метод skipWhile
пропускает элементы из коллекции, в то время как данный обратный вызов возвращает true
, а затем возвращает оставшиеся элементы в коллекции как новую коллекцию:
$collection = collect([1, 2, 3, 4]); $subset = $collection->skipWhile(function ($item) { return $item <= 3;}); $subset->all(); // [4]
{note} Если обратный вызов никогда не возвращает
false
, методskipWhile
вернет пустую коллекцию.
slice()
Метод slice
возвращает фрагмент коллекции, начиная с данного индекса:
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); $slice = $collection->slice(4); $slice->all(); // [5, 6, 7, 8, 9, 10]
Если вы хотите ограничить размер возвращаемого фрагмента, передайте желаемый размер в качестве второго аргумента метода:
$slice = $collection->slice(4, 2); $slice->all(); // [5, 6]
Возвращенный фрагмент по умолчанию сохранит ключи. Если вы не хотите сохранять исходные ключи, вы можете использовать метод values
для их переиндексации.
sole()
Метод sole
возвращает первый элемент в коллекции, который проходит заданную проверку истинности, но только если проверка истинности соответствует ровно одному элементу:
collect([1, 2, 3, 4])->sole(function ($value, $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()
Псевдоним для метода contains
.
sort()
Метод sort
сортирует коллекцию. Сортированная коллекция сохраняет исходные ключи массива, поэтому в следующем примере мы будем использовать метод values
для сброса ключей на последовательно пронумерованные индексы:
$collection = collect([5, 3, 1, 2, 4]); $sorted = $collection->sort(); $sorted->values()->all(); // [1, 2, 3, 4, 5]
Если ваши потребности в сортировке более сложные, вы можете передать обратный вызов sort
с вашим собственным алгоритмом. Обратитесь к документации PHP по uasort
, который является методом sort
коллекции вызовы используют внутренне.
{tip} Если вам нужно отсортировать коллекцию вложенных массивов или объектов, смотрите методы
sortBy
иsortByDesc
.
sortBy()
Метод sortBy
сортирует коллекцию по заданному ключу. Сортированная коллекция сохраняет исходные ключи массива, поэтому в следующем примере мы будем использовать метод values
для сброса ключей на последовательно пронумерованные индексы:
$collection = collect([ ['name' => 'Desk', 'price' => 200], ['name' => 'Chair', 'price' => 100], ['name' => 'Bookcase', 'price' => 150],]); $sorted = $collection->sortBy('price'); $sorted->values()->all(); /* [ ['name' => 'Chair', 'price' => 100], ['name' => 'Bookcase', 'price' => 150], ['name' => 'Desk', 'price' => 200], ]*/
Метод 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 ($product, $key) { return count($product['colors']);}); $sorted->values()->all(); /* [ ['name' => 'Chair', 'colors' => ['Black']], ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']], ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']], ]*/
Если вы хотите отсортировать свою коллекцию по нескольким атрибутам, вы можете передать массив операций сортировки методу sortBy
. Каждая операция сортировки должна быть массивом, состоящим из атрибута, по которому вы хотите выполнить сортировку, и направления желаемой сортировки:
$collection = collect([ ['name' => 'Taylor Otwell', 'age' => 34], ['name' => 'Abigail Otwell', 'age' => 30], ['name' => 'Taylor Otwell', 'age' => 36], ['name' => 'Abigail Otwell', 'age' => 32],]); $sorted = $collection->sortBy([ ['name', 'asc'], ['age', 'desc'],]); $sorted->values()->all(); /* [ ['name' => 'Abigail Otwell', 'age' => 32], ['name' => 'Abigail Otwell', 'age' => 30], ['name' => 'Taylor Otwell', 'age' => 36], ['name' => 'Taylor Otwell', 'age' => 34], ]*/
При сортировке коллекции по нескольким атрибутам вы также можете указать замыкания, которые определяют каждую операцию сортировки:
$collection = collect([ ['name' => 'Taylor Otwell', 'age' => 34], ['name' => 'Abigail Otwell', 'age' => 30], ['name' => 'Taylor Otwell', 'age' => 36], ['name' => 'Abigail Otwell', 'age' => 32],]); $sorted = $collection->sortBy([ fn ($a, $b) => $a['name'] <=> $b['name'], fn ($a, $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()
Этот метод имеет ту же сигнатуру, что и метод sortBy
, но сортирует коллекцию в обратном порядке.
sortDesc()
Этот метод сортирует коллекцию в порядке, обратном методу sort
:
$collection = collect([5, 3, 1, 2, 4]); $sorted = $collection->sortDesc(); $sorted->values()->all(); // [5, 4, 3, 2, 1]
В отличие от sort
, вы не можете передавать замыкание в sortDesc
. Вместо этого вы должны использовать метод sort
и инвертировать ваше сравнение.
sortKeys()
Метод sortKeys
сортирует коллекцию по ключам нижележащего ассоциативного массива:
$collection = collect([ 'id' => 22345, 'first' => 'John', 'last' => 'Doe',]); $sorted = $collection->sortKeys(); $sorted->all(); /* [ 'first' => 'John', 'id' => 22345, 'last' => 'Doe', ]*/
sortKeysDesc()
Этот метод имеет ту же сигнатуру, что и метод sortKeys
, но сортирует коллекцию в обратном порядке.
sortKeysUsing()
The sortKeysUsing
method sorts the collection by the keys of the underlying associative array using a callback:
$collection = collect([ 'ID' => 22345, 'first' => 'John', 'last' => 'Doe',]); $sorted = $collection->sortKeysUsing('strnatcasecmp'); $sorted->all(); /* [ 'first' => 'John', 'ID' => 22345, 'last' => 'Doe', ]*/
The callback must be a comparison function that returns an integer less than, equal to, or greater than zero. For more information, refer to the PHP documentation on uksort
, which is the PHP function that sortKeysUsing
method utilizes internally.
splice()
Метод splice
удаляет и возвращает часть элементов, начиная с указанного индекса:
$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2); $chunk->all(); // [3, 4, 5] $collection->all(); // [1, 2]
Вы можете передать второй аргумент, чтобы ограничить размер результирующей коллекции:
$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2, 1); $chunk->all(); // [3] $collection->all(); // [1, 2, 4, 5]
Кроме того, вы можете передать третий аргумент, содержащий новые элементы, чтобы заменить элементы, удаленные из коллекции:
$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2, 1, [10, 11]); $chunk->all(); // [3] $collection->all(); // [1, 2, 10, 11, 4, 5]
split()
Метод split
разбивает коллекцию на заданное количество групп:
$collection = collect([1, 2, 3, 4, 5]); $groups = $collection->split(3); $groups->all(); // [[1, 2], [3, 4], [5]]
splitIn()
Метод 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()
Метод sum
возвращает сумму всех элементов в коллекции:
collect([1, 2, 3, 4, 5])->sum(); // 15
Если коллекция содержит вложенные массивы или объекты, вы должны передать ключ, который будет использоваться для определения, какие значения следует суммировать:
$collection = collect([ ['name' => 'JavaScript: The Good Parts', 'pages' => 176], ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096],]); $collection->sum('pages'); // 1272
Кроме того, вы можете передать собственное замыкание, чтобы определить, какие значения коллекции нужно суммировать:
$collection = collect([ ['name' => 'Chair', 'colors' => ['Black']], ['name' => 'Desk', 'colors' => ['Black', 'Mahogany']], ['name' => 'Bookcase', 'colors' => ['Red', 'Beige', 'Brown']],]); $collection->sum(function ($product) { return count($product['colors']);}); // 6
take()
Метод take
возвращает новую коллекцию с указанным количеством элементов:
$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(3); $chunk->all(); // [0, 1, 2]
Вы также можете передать отрицательное целое число, чтобы взять указанное количество элементов из конца коллекции:
$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(-2); $chunk->all(); // [4, 5]
takeUntil()
Метод takeUntil
возвращает элементы в коллекции до тех пор, пока данный обратный вызов не вернет true
:
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(function ($item) { return $item >= 3;}); $subset->all(); // [1, 2]
Вы также можете передать простое значение методу takeUntil
, чтобы получать элементы, пока не будет найдено заданное значение:
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(3); $subset->all(); // [1, 2]
{note} Если данное значение не найдено или обратный вызов никогда не возвращает
true
, методtakeUntil
вернет все элементы в коллекции.
takeWhile()
Метод takeWhile
возвращает элементы в коллекции до тех пор, пока данный обратный вызов не вернет false
:
$collection = collect([1, 2, 3, 4]); $subset = $collection->takeWhile(function ($item) { return $item < 3;}); $subset->all(); // [1, 2]
{note} Если обратный вызов никогда не возвращает
false
, методtakeWhile
вернет все элементы в коллекции.
tap()
Метод tap
передает коллекцию заданному обратному вызову, позволяя вам «коснуться» коллекции в определенной точке и сделать что-то с элементами, не затрагивая саму коллекцию. Затем коллекция возвращается методом tap
:
collect([2, 4, 3, 1, 5]) ->sort() ->tap(function ($collection) { Log::debug('Values after sorting', $collection->values()->all()); }) ->shift(); // 1
times()
Статический метод times
создает новую коллекцию, вызывая заданное замыкание указанное количество раз:
$collection = Collection::times(10, function ($number) { return $number * 9;}); $collection->all(); // [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]
toArray()
Метод toArray
преобразует коллекцию в простой массив PHP array
. Если значениями коллекции являются модели Eloquent, модели также будут преобразованы в массивы:
$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toArray(); /* [ ['name' => 'Desk', 'price' => 200], ]*/
{note}
toArray
также преобразует все вложенные объекты коллекции, которые являются экземпляромArrayable
, в массив. Если вы хотите получить необработанный массив, лежащий в основе коллекции, используйте вместо этого методall
.
toJson()
Метод toJson
преобразует коллекцию в сериализованную строку JSON:
$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toJson(); // '{"name":"Desk", "price":200}'
transform()
Метод transform
выполняет итерацию по коллекции и вызывает заданный обратный вызов для каждого элемента в коллекции. Элементы в коллекции будут заменены значениями, возвращаемыми обратным вызовом:
$collection = collect([1, 2, 3, 4, 5]); $collection->transform(function ($item, $key) { return $item * 2;}); $collection->all(); // [2, 4, 6, 8, 10]
{note} В отличие от большинства других методов сбора,
transform
изменяет саму коллекцию. Если вы хотите вместо этого создать новую коллекцию, используйте методmap
.
undot()
The undot
method expands a single-dimensional collection that uses "dot" notation into a multi-dimensional collection:
$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()
Метод union
добавляет заданный массив в коллекцию. Если данный массив содержит ключи, которые уже находятся в исходной коллекции, предпочтительнее будут значения исходной коллекции:
$collection = collect([1 => ['a'], 2 => ['b']]); $union = $collection->union([3 => ['c'], 1 => ['d']]); $union->all(); // [1 => ['a'], 2 => ['b'], 3 => ['c']]
unique()
Метод unique
возвращает все уникальные элементы коллекции. Возвращенная коллекция сохраняет исходные ключи массива, поэтому в следующем примере мы будем использовать метод values
для сброса ключей на последовательно пронумерованные индексы:
$collection = collect([1, 1, 2, 2, 3, 4, 2]); $unique = $collection->unique(); $unique->values()->all(); // [1, 2, 3, 4]
При работе с вложенными массивами или объектами вы можете указать ключ, используемый для определения уникальности:
$collection = collect([ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'], ['name' => 'iPhone 5', 'brand' => 'Apple', 'type' => 'phone'], ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'], ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'],]); $unique = $collection->unique('brand'); $unique->values()->all(); /* [ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'], ]*/
Наконец, вы также можете передать собственное замыкание методу unique
, чтобы указать, какое значение должно определять уникальность элемента:
$unique = $collection->unique(function ($item) { return $item['brand'].$item['type'];}); $unique->values()->all(); /* [ ['name' => 'iPhone 6', 'brand' => 'Apple', 'type' => 'phone'], ['name' => 'Apple Watch', 'brand' => 'Apple', 'type' => 'watch'], ['name' => 'Galaxy S6', 'brand' => 'Samsung', 'type' => 'phone'], ['name' => 'Galaxy Gear', 'brand' => 'Samsung', 'type' => 'watch'], ]*/
Метод unique
использует «свободные» сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу того же значения. Используйте метод uniqueStrict
для фильтрации с использованием «строгих» сравнений.
{tip} Поведение этого метода изменяется при использовании Eloquent Collections.
uniqueStrict()
Этот метод имеет ту же сигнатуру, что и метод unique
; однако все значения сравниваются с использованием «строгих» сравнений.
unless()
Метод unless
выполнит заданный обратный вызов, если первый аргумент, переданный методу, не будет иметь значение true
:
$collection = collect([1, 2, 3]); $collection->unless(true, function ($collection) { return $collection->push(4);}); $collection->unless(false, function ($collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
Второй обратный вызов может быть передан методу unless
. Второй обратный вызов будет выполнен, когда первый аргумент, переданный методу unless
, оценивается как true
:
$collection = collect([1, 2, 3]); $collection->unless(true, function ($collection) { return $collection->push(4);}, function ($collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
Обратное к unless
, смотрите в методе when
.
unlessEmpty()
Псевдоним для метода whenNotEmpty
.
unlessNotEmpty()
Псевдоним для метода whenEmpty
.
unwrap()
Статический метод unwrap
возвращает базовые элементы коллекции из заданного значения, когда это применимо:
Collection::unwrap(collect('John Doe')); // ['John Doe'] Collection::unwrap(['John Doe']); // ['John Doe'] Collection::unwrap('John Doe'); // 'John Doe'
values()
Метод values
возвращает новую коллекцию с ключами, сброшенными на последовательные целые числа:
$collection = collect([ 10 => ['product' => 'Desk', 'price' => 200], 11 => ['product' => 'Desk', 'price' => 200],]); $values = $collection->values(); $values->all(); /* [ 0 => ['product' => 'Desk', 'price' => 200], 1 => ['product' => 'Desk', 'price' => 200], ]*/
when()
Метод when
выполнит данный обратный вызов, когда первый аргумент, переданный методу, оценивается как true
:
$collection = collect([1, 2, 3]); $collection->when(true, function ($collection) { return $collection->push(4);}); $collection->when(false, function ($collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 4]
Второй обратный вызов может быть передан методу when
. Второй обратный вызов будет выполнен, когда первый аргумент, переданный методу when
, оценивается как false
:
$collection = collect([1, 2, 3]); $collection->when(false, function ($collection) { return $collection->push(4);}, function ($collection) { return $collection->push(5);}); $collection->all(); // [1, 2, 3, 5]
Обратный метод when
можно найти в методе unless
.
whenEmpty()
Метод whenEmpty
выполнит данный обратный вызов, когда коллекция пуста:
$collection = collect(['Michael', 'Tom']); $collection->whenEmpty(function ($collection) { return $collection->push('Adam');}); $collection->all(); // ['Michael', 'Tom'] $collection = collect(); $collection->whenEmpty(function ($collection) { return $collection->push('Adam');}); $collection->all(); // ['Adam']
Второе замыкание может быть передано методу whenEmpty
, который будет выполнен, когда коллекция не пуста:
$collection = collect(['Michael', 'Tom']); $collection->whenEmpty(function ($collection) { return $collection->push('Adam');}, function ($collection) { return $collection->push('Taylor');}); $collection->all(); // ['Michael', 'Tom', 'Taylor']
Для обратного whenEmpty
, смотрите метод whenNotEmpty
.
whenNotEmpty()
Метод whenNotEmpty
выполнит данный обратный вызов, если коллекция не пуста:
$collection = collect(['michael', 'tom']); $collection->whenNotEmpty(function ($collection) { return $collection->push('adam');}); $collection->all(); // ['michael', 'tom', 'adam'] $collection = collect(); $collection->whenNotEmpty(function ($collection) { return $collection->push('adam');}); $collection->all(); // []
Второе замыкание может быть передано методу whenNotEmpty
, который будет выполняться, когда коллекция пуста:
$collection = collect(); $collection->whenNotEmpty(function ($collection) { return $collection->push('adam');}, function ($collection) { return $collection->push('taylor');}); $collection->all(); // ['taylor']
Для обратного whenNotEmpty
, смотрите метод whenEmpty
.
where()
Метод where
фильтрует коллекцию по заданной паре ключ / значение:
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100], ['product' => 'Bookcase', 'price' => 150], ['product' => 'Door', 'price' => 100],]); $filtered = $collection->where('price', 100); $filtered->all(); /* [ ['product' => 'Chair', 'price' => 100], ['product' => 'Door', 'price' => 100], ]*/
Метод where
использует «свободные» сравнения при проверке значений элементов, то есть строка с целочисленным значением будет считаться равной целому числу того же значения. Используйте метод whereStrict
для фильтрации с использованием «строгих» сравнений.
При желании вы можете передать оператор сравнения в качестве второго параметра.
$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()
Этот метод имеет ту же сигнатуру, что и метод where
; однако все значения сравниваются с использованием «строгих» сравнений.
whereBetween()
Метод 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()
Метод 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()
Этот метод имеет ту же сигнатуру, что и метод whereIn
; однако все значения сравниваются с использованием «строгих» сравнений.
whereInstanceOf()
Метод 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()
Метод 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()
Метод whereNotIn
удаляет элементы из коллекции, которые имеют указанное значение элемента, содержащееся в данном массиве:
$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100], ['product' => 'Bookcase', 'price' => 150], ['product' => 'Door', 'price' => 100],]); $filtered = $collection->whereNotIn('price', [150, 200]); $filtered->all(); /* [ ['product' => 'Chair', 'price' => 100], ['product' => 'Door', 'price' => 100], ]*/
Метод whereNotIn
использует «свободные» сравнения при проверке значений элементов, то есть строка с целым значением будет считаться равной целому числу того же значения. Используйте метод whereNotInStrict
для фильтрации с использованием «строгих» сравнений.
whereNotInStrict()
Этот метод имеет ту же сигнатуру, что и метод whereNotIn
; однако все значения сравниваются с использованием «строгих» сравнений.
whereNotNull()
Метод whereNotNull
возвращает элементы из коллекции, для которых заданный ключ не равен null
:
$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'],]); $filtered = $collection->whereNotNull('name'); $filtered->all(); /* [ ['name' => 'Desk'], ['name' => 'Bookcase'], ]*/
whereNull()
Метод whereNull
возвращает элементы из коллекции, для которых заданный ключ равен null
:
$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'],]); $filtered = $collection->whereNull('name'); $filtered->all(); /* [ ['name' => null], ]*/
wrap()
Статический метод 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()
Метод zip
объединяет значения данного массива со значениями исходной коллекции по их соответствующему индексу:
$collection = collect(['Chair', 'Desk']); $zipped = $collection->zip([100, 200]); $zipped->all(); // [['Chair', 100], ['Desk', 200]]
Сообщения высшего порядка
Коллекции также обеспечивают поддержку «сообщений более высокого порядка», которые являются сокращениями для выполнения общих действий с коллекциями. Методы сбора, которые предоставляют сообщения более высокого порядка: average
, avg
, contains
, each
, every
, filter
, first
, flatMap
, groupBy
, keyBy
, map
, max
, min
, partition
, reject
, skipUntil
, skipWhile
, some
, sortBy
, sortByDesc
, sum
, takeUntil
, takeWhile
и unique
.
К каждому сообщению более высокого порядка можно получить доступ как к динамическому свойству экземпляра коллекции. Например, давайте использовать сообщение более высокого порядка each
для вызова метода для каждого объекта в коллекции:
use App\Models\User; $users = User::where('votes', '>', 500)->get(); $users->each->markAsVip();
Точно так же мы можем использовать сообщение высшего порядка sum
, чтобы собрать общее количество «голосов» для набора пользователей:
$users = User::where('group', 'Development')->get(); return $users->sum->votes;
Отложенные коллекции
Введение
{note} Прежде чем узнать больше о отложенных коллекциях 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 ($lines) { return LogEntry::fromLines($lines);})->each(function (LogEntry $logEntry) { // Process the log entry...});
Или представьте, что вам нужно перебрать 10 000 моделей Eloquent. При использовании традиционных коллекций Laravel все 10 000 моделей Eloquent должны быть загружены в память одновременно:
use App\Models\User; $users = User::all()->filter(function ($user) { return $user->id > 500;});
Однако метод cursor
query builder возвращает экземпляр LazyCollection
. Это позволяет вам по-прежнему выполнять только один запрос к базе данных, но при этом одновременно загружать в память только одну модель Eloquent. В этом примере обратный вызов filter
не выполняется до тех пор, пока мы фактически не перебираем каждого пользователя индивидуально, что позволяет резко сократить использование памяти:
use App\Models\User; $users = User::cursor()->filter(function ($user) { return $user->id > 500;}); foreach ($users as $user) { echo $user->id;}
Создание отложенных коллекций
Чтобы создать экземпляр отложенной коллекции, вы должны передать функцию генератора PHP методу make
коллекции:
use Illuminate\Support\LazyCollection; LazyCollection::make(function () { $handle = fopen('log.txt', 'r'); while (($line = fgets($handle)) !== false) { yield $line; }});
Перечисляемый контракт
Почти все методы, доступные в классе Collection
, также доступны в классе LazyCollection
. Оба этих класса реализуют контракт Illuminate\Support\Enumerable
, который определяет следующие методы:
all average avg chunk chunkWhile collapse collect combine concat contains containsStrict count countBy crossJoin dd diff diffAssoc diffKeys dump duplicates duplicatesStrict each eachSpread every except filter first firstWhere flatMap flatten flip forPage get groupBy has implode intersect intersectByKeys isEmpty isNotEmpty join keyBy keys last macro make map mapInto mapSpread mapToGroups mapWithKeys max median merge mergeRecursive min mode nth only pad partition pipe pluck random reduce reject replace replaceRecursive reverse search shuffle skip slice some sort sortBy sortByDesc sortKeys sortKeysDesc split sum take tap times toArray toJson union unique uniqueStrict unless unlessEmpty unlessNotEmpty unwrap values when whenEmpty whenNotEmpty where whereStrict whereBetween whereIn whereInStrict whereInstanceOf whereNotBetween whereNotIn whereNotInStrict wrap zip
{note} Методы, которые изменяют коллекцию (такие как
shift
,pop
,prepend
и т. д.) недоступны в классеLazyCollection
.
Методы отложенных коллекций
В дополнение к методам, определенным в контракте Enumerable
, класс LazyCollection
содержит следующие методы:
takeUntilTimeout()
Метод takeUntilTimeout
возвращает новую отложенную коллекцию, которая будет перечислять значения до указанного времени. По истечении этого времени коллекция перестанет перечислять:
$lazyCollection = LazyCollection::times(INF) ->takeUntilTimeout(now()->addMinute()); $lazyCollection->each(function ($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->submit());
tapEach()
В то время как метод each
вызывает данный обратный вызов для каждого элемента в коллекции сразу, метод tapEach
вызывает данный обратный вызов только по мере того, как элементы извлекаются из списка один за другим:
// Пока ничего не сдампили...$lazyCollection = LazyCollection::times(INF)->tapEach(function ($value) { dump($value);}); // Дамп трёх элементов...$array = $lazyCollection->take(3)->all(); // 1// 2// 3
remember()
Метод remember
возвращает новую отложенную коллекцию, которая запоминает любые значения, которые уже были перечислены, и не будет извлекать их снова при последующих перечислениях коллекции:
// Запрос еще не выполнен...$users = User::cursor()->remember(); // Запрос выполняется...// Первые 5 пользователей гидратированы из базы данных...$users->take(5)->all(); // Первые 5 пользователей приходят из кеша коллекции...// Остальные гидратированы из базы данных...$users->take(20)->all();