CollectionsIntroductionThe Illuminate\Support\Collection class provides a fluent, convenient wrapper for working with arrays of data. For example, check out the following code. We'll use the collect helper to create a new collection instance from the array, run the strtoupper function on each element, and then remove all empty elements:$collection = collect(['taylor', 'abigail', null])->map(function ($name) { return strtoupper($name); })->reject(function ($name) { return empty($name); });As you can see, the Collection class allows you to chain its methods to perform fluent mapping and reducing of the underlying array. In general, collections are immutable, meaning every Collection method returns an entirely new Collection instance.Creating CollectionsAs mentioned above, the collect helper returns a new Illuminate\Support\Collection instance for the given array. So, creating a collection is as simple as:$collection = collect([1, 2, 3]);The results of Eloquent queries are always returned as Collection instances.Extending CollectionsCollections are "macroable", which allows you to add additional methods to the Collection class at run time. The Illuminate\Support\Collection class' macro method accepts a closure that will be executed when your macro is called. The macro closure may access the collection's other methods via $this, just as if it were a real method of the collection class. For example, the following code adds a toUpper method to the Collection class: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']Typically, you should declare collection macros in the boot method of a service provider.Macro ArgumentsIf necessary, you may define macros that accept additional arguments: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');Higher Order MessagesCollections also provide support for "higher order messages", which are short-cuts for performing common actions on collections. The collection methods that provide higher order messages are: average, avg, contains, each, every, filter, first, flatMap, groupBy, keyBy, map, max, min, partition, reject, skipUntil, skipWhile, some, sortBy, sortByDesc, sum, takeUntil, takeWhile, and unique.Each higher order message can be accessed as a dynamic property on a collection instance. For instance, let's use the each higher order message to call a method on each object within a collection:use App\Models\User; $users = User::where('votes', '>', 500)->get(); $users->each->markAsVip();Likewise, we can use the sum higher order message to gather the total number of "votes" for a collection of users:$users = User::where('group', 'Development')->get(); return $users->sum->votes;Available MethodsFor the majority of the remaining collection documentation, we'll discuss each method available on the Collection class. Remember, all of these methods may be chained to fluently manipulate the underlying array. Furthermore, almost every method returns a new Collection instance, allowing you to preserve the original copy of the collection when necessary:allaverageavgchunkchunkWhilecollapsecollectcombineconcatcontainscontainsStrictcountcountBycrossJoindddiffdiffAssocdiffKeysdoesntContaindumpduplicatesduplicatesStricteacheachSpreadeveryexceptfilterfirstfirstWhereflatMapflattenflipforgetforPagegetgroupByhasimplodeintersectintersectByKeysisEmptyisNotEmptyjoinkeyBykeyslastmacromakemapmapIntomapSpreadmapToGroupsmapWithKeysmaxmedianmergemergeRecursiveminmodenthonlypadpartitionpipepipeIntopipeThroughpluckpopprependpullpushputrandomrangereducereduceSpreadrejectreplacereplaceRecursivereversesearchshiftshuffleslidingskipskipUntilskipWhileslicesolesomesortsortBysortByDescsortDescsortKeyssortKeysDescsortKeysUsingsplicesplitsplitInsumtaketakeUntiltakeWhiletaptimestoArraytoJsontransformundotunionuniqueuniqueStrictunlessunlessEmptyunlessNotEmptyunwrapvalueswhenwhenEmptywhenNotEmptywherewhereStrictwhereBetweenwhereInwhereInStrictwhereInstanceOfwhereNotBetweenwhereNotInwhereNotInStrictwhereNotNullwhereNullwrapzipMethod Listingall()The all method returns the underlying array represented by the collection:collect([1, 2, 3])->all(); // [1, 2, 3]average()Alias for the avg method.avg()The avg method returns the average value of a given key:$average = collect([ ['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40] ])->avg('foo'); // 20 $average = collect([1, 1, 2, 4])->avg(); // 2chunk()The chunk method breaks the collection into multiple, smaller collections of a given size:$collection = collect([1, 2, 3, 4, 5, 6, 7]); $chunks = $collection->chunk(4); $chunks->all(); // [[1, 2, 3, 4], [5, 6, 7]]This method is especially useful in views when working with a grid system such as Bootstrap. For example, imagine you have a collection of Eloquent models you want to display in a grid:@foreach ($products->chunk(3) as $chunk) @foreach ($chunk as $product) {{ $product->name }} @endforeach @endforeachchunkWhile()The chunkWhile method breaks the collection into multiple, smaller collections based on the evaluation of the given callback. The $chunk variable passed to the closure may be used to inspect the previous element:$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()The collapse method collapses a collection of arrays into a single, flat collection:$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()The collect method returns a new Collection instance with the items currently in the collection:$collectionA = collect([1, 2, 3]); $collectionB = $collectionA->collect(); $collectionB->all(); // [1, 2, 3]The collect method is primarily useful for converting lazy collections into standard Collection instances:$lazyCollection = LazyCollection::make(function () { yield 1; yield 2; yield 3; }); $collection = $lazyCollection->collect(); get_class($collection); // 'Illuminate\Support\Collection' $collection->all(); // [1, 2, 3]The collect method is especially useful when you have an instance of Enumerable and need a non-lazy collection instance. Since collect() is part of the Enumerable contract, you can safely use it to get a Collection instance.combine()The combine method combines the values of the collection, as keys, with the values of another array or collection:$collection = collect(['name', 'age']); $combined = $collection->combine(['George', 29]); $combined->all(); // ['name' => 'George', 'age' => 29]concat()The concat method appends the given array or collection's values onto the end of another collection:$collection = collect(['John Doe']); $concatenated = $collection->concat(['Jane Doe'])->concat(['name' => 'Johnny Doe']); $concatenated->all(); // ['John Doe', 'Jane Doe', 'Johnny Doe']contains()The contains method determines whether the collection contains a given item. You may pass a closure to the contains method to determine if an element exists in the collection matching a given truth test:$collection = collect([1, 2, 3, 4, 5]); $collection->contains(function ($value, $key) { return $value > 5; }); // falseAlternatively, you may pass a string to the contains method to determine whether the collection contains a given item value:$collection = collect(['name' => 'Desk', 'price' => 100]); $collection->contains('Desk'); // true $collection->contains('New York'); // falseYou may also pass a key / value pair to the contains method, which will determine if the given pair exists in the collection:$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100], ]); $collection->contains('product', 'Bookcase'); // falseThe contains 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. Use the containsStrict method to filter using "strict" comparisons.For the inverse of contains, see the doesntContain method.containsStrict()This method has the same signature as the contains method; however, all values are compared using "strict" comparisons.This method's behavior is modified when using Eloquent Collections.count()The count method returns the total number of items in the collection:$collection = collect([1, 2, 3, 4]); $collection->count(); // 4countBy()The countBy method counts the occurrences of values in the collection. By default, the method counts the occurrences of every element, allowing you to count certain "types" of elements in the collection:$collection = collect([1, 2, 2, 2, 3]); $counted = $collection->countBy(); $counted->all(); // [1 => 1, 2 => 3, 3 => 1]You pass a closure to the countBy method to count all items by a custom value:$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()The crossJoin method cross joins the collection's values among the given arrays or collections, returning a Cartesian product with all possible permutations:$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()The dd method dumps the collection's items and ends execution of the script:$collection = collect(['John Doe', 'Jane Doe']); $collection->dd(); /* Collection { #items: array:2 [ 0 => "John Doe" 1 => "Jane Doe" ] } */If you do not want to stop executing the script, use the dump method instead.diff()The diff method compares the collection against another collection or a plain PHP array based on its values. This method will return the values in the original collection that are not present in the given collection:$collection = collect([1, 2, 3, 4, 5]); $diff = $collection->diff([2, 4, 6, 8]); $diff->all(); // [1, 3, 5]This method's behavior is modified when using Eloquent Collections.diffAssoc()The diffAssoc method compares the collection against another collection or a plain PHP array based on its keys and values. This method will return the key / value pairs in the original collection that are not present in the given collection:$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()The diffKeys method compares the collection against another collection or a plain PHP array based on its keys. This method will return the key / value pairs in the original collection that are not present in the given collection:$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; }); // falseAlternatively, 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'); // falseYou 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'); // trueThe 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()The dump method dumps the collection's items:$collection = collect(['John Doe', 'Jane Doe']); $collection->dump(); /* Collection { #items: array:2 [ 0 => "John Doe" 1 => "Jane Doe" ] } */If you want to stop executing the script after dumping the collection, use the dd method instead.duplicates()The duplicates method retrieves and returns duplicate values from the collection:$collection = collect(['a', 'b', 'a', 'c', 'b']); $collection->duplicates(); // [2 => 'a', 4 => 'b']If the collection contains arrays or objects, you can pass the key of the attributes that you wish to check for duplicate values:$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()This method has the same signature as the duplicates method; however, all values are compared using "strict" comparisons.each()The each method iterates over the items in the collection and passes each item to a closure:$collection->each(function ($item, $key) { // });If you would like to stop iterating through the items, you may return false from your closure:$collection->each(function ($item, $key) { if (/* condition */) { return false; } });eachSpread()The eachSpread method iterates over the collection's items, passing each nested item value into the given callback:$collection = collect([['John Doe', 35], ['Jane Doe', 33]]); $collection->eachSpread(function ($name, $age) { // });You may stop iterating through the items by returning false from the callback:$collection->eachSpread(function ($name, $age) { return false; });every()The every method may be used to verify that all elements of a collection pass a given truth test:collect([1, 2, 3, 4])->every(function ($value, $key) { return $value > 2; }); // falseIf the collection is empty, the every method will return true:$collection = collect([]); $collection->every(function ($value, $key) { return $value > 2; }); // trueexcept()The except method returns all items in the collection except for those with the specified keys:$collection = collect(['product_id' => 1, 'price' => 100, 'discount' => false]); $filtered = $collection->except(['price', 'discount']); $filtered->all(); // ['product_id' => 1]For the inverse of except, see the only method.This method's behavior is modified when using Eloquent Collections.filter()The filter method filters the collection using the given callback, keeping only those items that pass a given truth test:$collection = collect([1, 2, 3, 4]); $filtered = $collection->filter(function ($value, $key) { return $value > 2; }); $filtered->all(); // [3, 4]If no callback is supplied, all entries of the collection that are equivalent to false will be removed:$collection = collect([1, 2, 3, null, false, '', 0, []]); $collection->filter()->all(); // [1, 2, 3]For the inverse of filter, see the reject method.first()The first method returns the first element in the collection that passes a given truth test:collect([1, 2, 3, 4])->first(function ($value, $key) { return $value > 2; }); // 3You may also call the first method with no arguments to get the first element in the collection. If the collection is empty, null is returned:collect([1, 2, 3, 4])->first(); // 1firstWhere()The firstWhere method returns the first element in the collection with the given key / value pair:$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]You may also call the firstWhere method with a comparison operator:$collection->firstWhere('age', '>=', 18); // ['name' => 'Diego', 'age' => 23]Like the where method, you may pass one argument to the firstWhere method. In this scenario, the firstWhere method will return the first item where the given item key's value is "truthy":$collection->firstWhere('age'); // ['name' => 'Linda', 'age' => 14]flatMap()The flatMap method iterates through the collection and passes each value to the given closure. The closure is free to modify the item and return it, thus forming a new collection of modified items. Then, the array is flattened by one level:$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()The flatten method flattens a multi-dimensional collection into a single dimension:$collection = collect([ 'name' => 'taylor', 'languages' => [ 'php', 'javascript' ] ]); $flattened = $collection->flatten(); $flattened->all(); // ['taylor', 'php', 'javascript'];If necessary, you may pass the flatten method a "depth" argument:$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'], ] */In this example, calling flatten without providing the depth would have also flattened the nested arrays, resulting in ['iPhone 6S', 'Apple', 'Galaxy S7', 'Samsung']. Providing a depth allows you to specify the number of levels nested arrays will be flattened.flip()The flip method swaps the collection's keys with their corresponding values:$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $flipped = $collection->flip(); $flipped->all(); // ['taylor' => 'name', 'laravel' => 'framework']forget()The forget method removes an item from the collection by its key:$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $collection->forget('name'); $collection->all(); // ['framework' => 'laravel']Unlike most other collection methods, forget does not return a new modified collection; it modifies the collection it is called on.forPage()The forPage method returns a new collection containing the items that would be present on a given page number. The method accepts the page number as its first argument and the number of items to show per page as its second argument:$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]); $chunk = $collection->forPage(2, 3); $chunk->all(); // [4, 5, 6]get()The get method returns the item at a given key. If the key does not exist, null is returned:$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $value = $collection->get('name'); // taylorYou may optionally pass a default value as the second argument:$collection = collect(['name' => 'taylor', 'framework' => 'laravel']); $value = $collection->get('age', 34); // 34You may even pass a callback as the method's default value. The result of the callback will be returned if the specified key does not exist:$collection->get('email', function () { return 'taylor@example.com'; }); // taylor@example.comgroupBy()The groupBy method groups the collection's items by a given key:$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'], ], ] */Instead of passing a string key, you may pass a callback. The callback should return the value you wish to key the group by:$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'], ], ] */Multiple grouping criteria may be passed as an array. Each array element will be applied to the corresponding level within a multi-dimensional array:$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()The has method determines if a given key exists in the collection:$collection = collect(['account_id' => 1, 'product' => 'Desk', 'amount' => 5]); $collection->has('product'); // true $collection->has(['product', 'amount']); // true $collection->has(['amount', 'price']); // falseimplode()The implode method joins items in a collection. Its arguments depend on the type of items in the collection. If the collection contains arrays or objects, you should pass the key of the attributes you wish to join, and the "glue" string you wish to place between the values:$collection = collect([ ['account_id' => 1, 'product' => 'Desk'], ['account_id' => 2, 'product' => 'Chair'], ]); $collection->implode('product', ', '); // Desk, ChairIf the collection contains simple strings or numeric values, you should pass the "glue" as the only argument to the method:collect([1, 2, 3, 4, 5])->implode('-'); // '1-2-3-4-5'intersect()The intersect method removes any values from the original collection that are not present in the given array or collection. The resulting collection will preserve the original collection's keys:$collection = collect(['Desk', 'Sofa', 'Chair']); $intersect = $collection->intersect(['Desk', 'Chair', 'Bookcase']); $intersect->all(); // [0 => 'Desk', 2 => 'Chair']This method's behavior is modified when using Eloquent Collections.intersectByKeys()The intersectByKeys method removes any keys and their corresponding values from the original collection that are not present in the given array or collection:$collection = collect([ 'serial' => 'UX301', 'type' => 'screen', 'year' => 2009, ]); $intersect = $collection->intersectByKeys([ 'reference' => 'UX404', 'type' => 'tab', 'year' => 2011, ]); $intersect->all(); // ['type' => 'screen', 'year' => 2009]isEmpty()The isEmpty method returns true if the collection is empty; otherwise, false is returned:collect([])->isEmpty(); // trueisNotEmpty()The isNotEmpty method returns true if the collection is not empty; otherwise, false is returned:collect([])->isNotEmpty(); // falsejoin()The join method joins the collection's values with a string. Using this method's second argument, you may also specify how the final element should be appended to the string: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()The keyBy method keys the collection by the given key. If multiple items have the same key, only the last one will appear in the new collection:$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'], ] */You may also pass a callback to the method. The callback should return the value to key the collection by:$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()The keys method returns all of the collection's 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()The last method returns the last element in the collection that passes a given truth test:collect([1, 2, 3, 4])->last(function ($value, $key) { return $value < 3; }); // 2You may also call the last method with no arguments to get the last element in the collection. If the collection is empty, null is returned:collect([1, 2, 3, 4])->last(); // 4macro()The static macro method allows you to add methods to the Collection class at run time. Refer to the documentation on extending collections for more information.make()The static make method creates a new collection instance. See the Creating Collections section.map()The map method iterates through the collection and passes each value to the given callback. The callback is free to modify the item and return it, thus forming a new collection of modified items:$collection = collect([1, 2, 3, 4, 5]); $multiplied = $collection->map(function ($item, $key) { return $item * 2; }); $multiplied->all(); // [2, 4, 6, 8, 10]Like most other collection methods, map returns a new collection instance; it does not modify the collection it is called on. If you want to transform the original collection, use the transform method.mapInto()The mapInto() method iterates over the collection, creating a new instance of the given class by passing the value into the constructor: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()The mapSpread method iterates over the collection's items, passing each nested item value into the given closure. The closure is free to modify the item and return it, thus forming a new collection of modified items:$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()The mapToGroups method groups the collection's items by the given closure. The closure should return an associative array containing a single key / value pair, thus forming a new collection of grouped values:$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()The mapWithKeys method iterates through the collection and passes each value to the given callback. The callback should return an associative array containing a single key / value pair:$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()The max method returns the maximum value of a given key:$max = collect([ ['foo' => 10], ['foo' => 20] ])->max('foo'); // 20 $max = collect([1, 2, 3, 4, 5])->max(); // 5median()The median method returns the median value of a given key:$median = collect([ ['foo' => 10], ['foo' => 10], ['foo' => 20], ['foo' => 40] ])->median('foo'); // 15 $median = collect([1, 1, 2, 4])->median(); // 1.5merge()The merge method merges the given array or collection with the original collection. If a string key in the given items matches a string key in the original collection, the given items's value will overwrite the value in the original collection:$collection = collect(['product_id' => 1, 'price' => 100]); $merged = $collection->merge(['price' => 200, 'discount' => false]); $merged->all(); // ['product_id' => 1, 'price' => 200, 'discount' => false]If the given items's keys are numeric, the values will be appended to the end of the collection:$collection = collect(['Desk', 'Chair']); $merged = $collection->merge(['Bookcase', 'Door']); $merged->all(); // ['Desk', 'Chair', 'Bookcase', 'Door']mergeRecursive()The mergeRecursive method merges the given array or collection recursively with the original collection. If a string key in the given items matches a string key in the original collection, then the values for these keys are merged together into an array, and this is done recursively:$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()The min method returns the minimum value of a given key:$min = collect([['foo' => 10], ['foo' => 20]])->min('foo'); // 10 $min = collect([1, 2, 3, 4, 5])->min(); // 1mode()The mode method returns the mode value) of a given key:$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()The nth method creates a new collection consisting of every n-th element:$collection = collect(['a', 'b', 'c', 'd', 'e', 'f']); $collection->nth(4); // ['a', 'e']You may optionally pass a starting offset as the second argument:$collection->nth(4, 1); // ['b', 'f']only()The only method returns the items in the collection with the specified keys:$collection = collect([ 'product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false ]); $filtered = $collection->only(['product_id', 'name']); $filtered->all(); // ['product_id' => 1, 'name' => 'Desk']For the inverse of only, see the except method.This method's behavior is modified when using Eloquent Collections.pad()The pad method will fill the array with the given value until the array reaches the specified size. This method behaves like the array_pad PHP function.To pad to the left, you should specify a negative size. No padding will take place if the absolute value of the given size is less than or equal to the length of the array:$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()The partition method may be combined with PHP array destructuring to separate elements that pass a given truth test from those that do not:$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()The pipe method passes the collection to the given closure and returns the result of the executed closure:$collection = collect([1, 2, 3]); $piped = $collection->pipe(function ($collection) { return $collection->sum(); }); // 6pipeInto()The pipeInto method creates a new instance of the given class and passes the collection into the constructor: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(); }, ]); // 15pluck()The pluck method retrieves all of the values for a given key:$collection = collect([ ['product_id' => 'prod-100', 'name' => 'Desk'], ['product_id' => 'prod-200', 'name' => 'Chair'], ]); $plucked = $collection->pluck('name'); $plucked->all(); // ['Desk', 'Chair']You may also specify how you wish the resulting collection to be keyed:$plucked = $collection->pluck('name', 'product_id'); $plucked->all(); // ['prod-100' => 'Desk', 'prod-200' => 'Chair']The pluck method also supports retrieving nested values using "dot" notation:$collection = collect([ [ 'speakers' => [ 'first_day' => ['Rosa', 'Judith'], 'second_day' => ['Angela', 'Kathleen'], ], ], ]); $plucked = $collection->pluck('speakers.first_day'); $plucked->all(); // ['Rosa', 'Judith']If duplicate keys exist, the last matching element will be inserted into the plucked collection:$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()The pop method removes and returns the last item from the collection:$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()The prepend method adds an item to the beginning of the collection:$collection = collect([1, 2, 3, 4, 5]); $collection->prepend(0); $collection->all(); // [0, 1, 2, 3, 4, 5]You may also pass a second argument to specify the key of the prepended item:$collection = collect(['one' => 1, 'two' => 2]); $collection->prepend(0, 'zero'); $collection->all(); // ['zero' => 0, 'one' => 1, 'two' => 2]pull()The pull method removes and returns an item from the collection by its key:$collection = collect(['product_id' => 'prod-100', 'name' => 'Desk']); $collection->pull('name'); // 'Desk' $collection->all(); // ['product_id' => 'prod-100']push()The push method appends an item to the end of the collection:$collection = collect([1, 2, 3, 4]); $collection->push(5); $collection->all(); // [1, 2, 3, 4, 5]put()The put method sets the given key and value in the collection:$collection = collect(['product_id' => 1, 'name' => 'Desk']); $collection->put('price', 100); $collection->all(); // ['product_id' => 1, 'name' => 'Desk', 'price' => 100]random()The random method returns a random item from the collection:$collection = collect([1, 2, 3, 4, 5]); $collection->random(); // 4 - (retrieved randomly)You may pass an integer to random to specify how many items you would like to randomly retrieve. A collection of items is always returned when explicitly passing the number of items you wish to receive:$random = $collection->random(3); $random->all(); // [2, 4, 5] - (retrieved randomly)If the collection instance has fewer items than requested, the random method will throw an 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()The reduce method reduces the collection to a single value, passing the result of each iteration into the subsequent iteration:$collection = collect([1, 2, 3]); $total = $collection->reduce(function ($carry, $item) { return $carry + $item; }); // 6The value for $carry on the first iteration is null; however, you may specify its initial value by passing a second argument to reduce:$collection->reduce(function ($carry, $item) { return $carry + $item; }, 4); // 10The reduce method also passes array keys in associative collections to the given callback:$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]); }); // 4264reduceSpread()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()The reject method filters the collection using the given closure. The closure should return true if the item should be removed from the resulting collection:$collection = collect([1, 2, 3, 4]); $filtered = $collection->reject(function ($value, $key) { return $value > 2; }); $filtered->all(); // [1, 2]For the inverse of the reject method, see the filter method.replace()The replace method behaves similarly to merge; however, in addition to overwriting matching items that have string keys, the replace method will also overwrite items in the collection that have matching numeric keys:$collection = collect(['Taylor', 'Abigail', 'James']); $replaced = $collection->replace([1 => 'Victoria', 3 => 'Finn']); $replaced->all(); // ['Taylor', 'Victoria', 'James', 'Finn']replaceRecursive()This method works like replace, but it will recur into arrays and apply the same replacement process to the inner values:$collection = collect([ 'Taylor', 'Abigail', [ 'James', 'Victoria', 'Finn' ] ]); $replaced = $collection->replaceRecursive([ 'Charlie', 2 => [1 => 'King'] ]); $replaced->all(); // ['Charlie', 'Abigail', ['James', 'King', 'Finn']]reverse()The reverse method reverses the order of the collection's items, preserving the original keys:$collection = collect(['a', 'b', 'c', 'd', 'e']); $reversed = $collection->reverse(); $reversed->all(); /* [ 4 => 'e', 3 => 'd', 2 => 'c', 1 => 'b', 0 => 'a', ] */search()The search method searches the collection for the given value and returns its key if found. If the item is not found, false is returned:$collection = collect([2, 4, 6, 8]); $collection->search(4); // 1The search is done using a "loose" comparison, meaning a string with an integer value will be considered equal to an integer of the same value. To use "strict" comparison, pass true as the second argument to the method:collect([2, 4, 6, 8])->search('4', $strict = true); // falseAlternatively, you may provide your own closure to search for the first item that passes a given truth test:collect([2, 4, 6, 8])->search(function ($item, $key) { return $item > 5; }); // 2shift()The shift method removes and returns the first item from the collection:$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()The shuffle method randomly shuffles the items in the collection:$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()The skip method returns a new collection, with the given number of elements removed from the beginning of the collection:$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()The skipUntil method skips over items from the collection until the given callback returns true and then returns the remaining items in the collection as a new collection instance:$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(function ($item) { return $item >= 3; }); $subset->all(); // [3, 4]You may also pass a simple value to the skipUntil method to skip all items until the given value is found:$collection = collect([1, 2, 3, 4]); $subset = $collection->skipUntil(3); $subset->all(); // [3, 4]If the given value is not found or the callback never returns true, the skipUntil method will return an empty collection.skipWhile()The skipWhile method skips over items from the collection while the given callback returns true and then returns the remaining items in the collection as a new collection:$collection = collect([1, 2, 3, 4]); $subset = $collection->skipWhile(function ($item) { return $item <= 3; }); $subset->all(); // [4]If the callback never returns false, the skipWhile method will return an empty collection.slice()The slice method returns a slice of the collection starting at the given index:$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); $slice = $collection->slice(4); $slice->all(); // [5, 6, 7, 8, 9, 10]If you would like to limit the size of the returned slice, pass the desired size as the second argument to the method:$slice = $collection->slice(4, 2); $slice->all(); // [5, 6]The returned slice will preserve keys by default. If you do not wish to preserve the original keys, you can use the values method to reindex them.sole()The sole method returns the first element in the collection that passes a given truth test, but only if the truth test matches exactly one element:collect([1, 2, 3, 4])->sole(function ($value, $key) { return $value === 2; }); // 2You may also pass a key / value pair to the sole method, which will return the first element in the collection that matches the given pair, but only if it exactly one element matches:$collection = collect([ ['product' => 'Desk', 'price' => 200], ['product' => 'Chair', 'price' => 100], ]); $collection->sole('product', 'Chair'); // ['product' => 'Chair', 'price' => 100]Alternatively, you may also call the sole method with no argument to get the first element in the collection if there is only one element:$collection = collect([ ['product' => 'Desk', 'price' => 200], ]); $collection->sole(); // ['product' => 'Desk', 'price' => 200]If there are no elements in the collection that should be returned by the sole method, an \Illuminate\Collections\ItemNotFoundException exception will be thrown. If there is more than one element that should be returned, an \Illuminate\Collections\MultipleItemsFoundException will be thrown.some()Alias for the contains method.sort()The sort method sorts the collection. The sorted collection keeps the original array keys, so in the following example we will use the values method to reset the keys to consecutively numbered indexes:$collection = collect([5, 3, 1, 2, 4]); $sorted = $collection->sort(); $sorted->values()->all(); // [1, 2, 3, 4, 5]If your sorting needs are more advanced, you may pass a callback to sort with your own algorithm. Refer to the PHP documentation on uasort, which is what the collection's sort method calls utilizes internally.If you need to sort a collection of nested arrays or objects, see the sortBy and sortByDesc methods.sortBy()The sortBy method sorts the collection by the given key. The sorted collection keeps the original array keys, so in the following example we will use the values method to reset the keys to consecutively numbered indexes:$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], ] */The sortBy method accepts sort flags as its second argument:$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'], ] */Alternatively, you may pass your own closure to determine how to sort the collection's values:$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']], ] */If you would like to sort your collection by multiple attributes, you may pass an array of sort operations to the sortBy method. Each sort operation should be an array consisting of the attribute that you wish to sort by and the direction of the desired sort:$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], ] */When sorting a collection by multiple attributes, you may also provide closures that define each sort operation:$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()This method has the same signature as the sortBy method, but will sort the collection in the opposite order.sortDesc()This method will sort the collection in the opposite order as the sort method:$collection = collect([5, 3, 1, 2, 4]); $sorted = $collection->sortDesc(); $sorted->values()->all(); // [5, 4, 3, 2, 1]Unlike sort, you may not pass a closure to sortDesc. Instead, you should use the sort method and invert your comparison.sortKeys()The sortKeys method sorts the collection by the keys of the underlying associative array:$collection = collect([ 'id' => 22345, 'first' => 'John', 'last' => 'Doe', ]); $sorted = $collection->sortKeys(); $sorted->all(); /* [ 'first' => 'John', 'id' => 22345, 'last' => 'Doe', ] */sortKeysDesc()This method has the same signature as the sortKeys method, but will sort the collection in the opposite order.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()The splice method removes and returns a slice of items starting at the specified index:$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2); $chunk->all(); // [3, 4, 5] $collection->all(); // [1, 2]You may pass a second argument to limit the size of the resulting collection:$collection = collect([1, 2, 3, 4, 5]); $chunk = $collection->splice(2, 1); $chunk->all(); // [3] $collection->all(); // [1, 2, 4, 5]In addition, you may pass a third argument containing the new items to replace the items removed from the collection:$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()The split method breaks a collection into the given number of groups:$collection = collect([1, 2, 3, 4, 5]); $groups = $collection->split(3); $groups->all(); // [[1, 2], [3, 4], [5]]splitIn()The splitIn method breaks a collection into the given number of groups, filling non-terminal groups completely before allocating the remainder to the final group:$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()The sum method returns the sum of all items in the collection:collect([1, 2, 3, 4, 5])->sum(); // 15If the collection contains nested arrays or objects, you should pass a key that will be used to determine which values to sum:$collection = collect([ ['name' => 'JavaScript: The Good Parts', 'pages' => 176], ['name' => 'JavaScript: The Definitive Guide', 'pages' => 1096], ]); $collection->sum('pages'); // 1272In addition, you may pass your own closure to determine which values of the collection to sum:$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']); }); // 6take()The take method returns a new collection with the specified number of items:$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(3); $chunk->all(); // [0, 1, 2]You may also pass a negative integer to take the specified number of items from the end of the collection:$collection = collect([0, 1, 2, 3, 4, 5]); $chunk = $collection->take(-2); $chunk->all(); // [4, 5]takeUntil()The takeUntil method returns items in the collection until the given callback returns true:$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(function ($item) { return $item >= 3; }); $subset->all(); // [1, 2]You may also pass a simple value to the takeUntil method to get the items until the given value is found:$collection = collect([1, 2, 3, 4]); $subset = $collection->takeUntil(3); $subset->all(); // [1, 2]If the given value is not found or the callback never returns true, the takeUntil method will return all items in the collection.takeWhile()The takeWhile method returns items in the collection until the given callback returns false:$collection = collect([1, 2, 3, 4]); $subset = $collection->takeWhile(function ($item) { return $item < 3; }); $subset->all(); // [1, 2]If the callback never returns false, the takeWhile method will return all items in the collection.tap()The tap method passes the collection to the given callback, allowing you to "tap" into the collection at a specific point and do something with the items while not affecting the collection itself. The collection is then returned by the tap method:collect([2, 4, 3, 1, 5]) ->sort() ->tap(function ($collection) { Log::debug('Values after sorting', $collection->values()->all()); }) ->shift(); // 1times()The static times method creates a new collection by invoking the given closure a specified number of times:$collection = Collection::times(10, function ($number) { return $number * 9; }); $collection->all(); // [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]toArray()The toArray method converts the collection into a plain PHP array. If the collection's values are Eloquent models, the models will also be converted to arrays:$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toArray(); /* [ ['name' => 'Desk', 'price' => 200], ] */toArray also converts all of the collection's nested objects that are an instance of Arrayable to an array. If you want to get the raw array underlying the collection, use the all method instead.toJson()The toJson method converts the collection into a JSON serialized string:$collection = collect(['name' => 'Desk', 'price' => 200]); $collection->toJson(); // '{"name":"Desk", "price":200}'transform()The transform method iterates over the collection and calls the given callback with each item in the collection. The items in the collection will be replaced by the values returned by the callback:$collection = collect([1, 2, 3, 4, 5]); $collection->transform(function ($item, $key) { return $item * 2; }); $collection->all(); // [2, 4, 6, 8, 10]Unlike most other collection methods, transform modifies the collection itself. If you wish to create a new collection instead, use the map method.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()The union method adds the given array to the collection. If the given array contains keys that are already in the original collection, the original collection's values will be preferred:$collection = collect([1 => ['a'], 2 => ['b']]); $union = $collection->union([3 => ['c'], 1 => ['d']]); $union->all(); // [1 => ['a'], 2 => ['b'], 3 => ['c']]unique()The unique method returns all of the unique items in the collection. The returned collection keeps the original array keys, so in the following example we will use the values method to reset the keys to consecutively numbered indexes:$collection = collect([1, 1, 2, 2, 3, 4, 2]); $unique = $collection->unique(); $unique->values()->all(); // [1, 2, 3, 4]When dealing with nested arrays or objects, you may specify the key used to determine uniqueness:$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'], ] */Finally, you may also pass your own closure to the unique method to specify which value should determine an item's uniqueness:$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'], ] */The unique 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. Use the uniqueStrict method to filter using "strict" comparisons.This method's behavior is modified when using Eloquent Collections.uniqueStrict()This method has the same signature as the unique method; however, all values are compared using "strict" comparisons.unless()The unless method will execute the given callback unless the first argument given to the method evaluates to 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]A second callback may be passed to the unless method. The second callback will be executed when the first argument given to the unless method evaluates to 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]For the inverse of unless, see the when method.unlessEmpty()Alias for the whenNotEmpty method.unlessNotEmpty()Alias for the whenEmpty method.unwrap()The static unwrap method returns the collection's underlying items from the given value when applicable:Collection::unwrap(collect('John Doe')); // ['John Doe'] Collection::unwrap(['John Doe']); // ['John Doe'] Collection::unwrap('John Doe'); // 'John Doe'values()The values method returns a new collection with the keys reset to consecutive integers:$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()The when method will execute the given callback when the first argument given to the method evaluates to 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]A second callback may be passed to the when method. The second callback will be executed when the first argument given to the when method evaluates to 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]For the inverse of when, see the unless method.whenEmpty()The whenEmpty method will execute the given callback when the collection is empty:$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']A second closure may be passed to the whenEmpty method that will be executed when the collection is not empty:$collection = collect(['Michael', 'Tom']); $collection->whenEmpty(function ($collection) { return $collection->push('Adam'); }, function ($collection) { return $collection->push('Taylor'); }); $collection->all(); // ['Michael', 'Tom', 'Taylor']For the inverse of whenEmpty, see the whenNotEmpty method.whenNotEmpty()The whenNotEmpty method will execute the given callback when the collection is not empty:$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(); // []A second closure may be passed to the whenNotEmpty method that will be executed when the collection is empty:$collection = collect(); $collection->whenNotEmpty(function ($collection) { return $collection->push('adam'); }, function ($collection) { return $collection->push('taylor'); }); $collection->all(); // ['taylor']For the inverse of whenNotEmpty, see the whenEmpty method.where()The where method filters the collection by a given key / value pair:$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], ] */The where 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. Use the whereStrict method to filter using "strict" comparisons.Optionally, you may pass a comparison operator as the second parameter.$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()This method has the same signature as the where method; however, all values are compared using "strict" comparisons.whereBetween()The whereBetween method filters the collection by determining if a specified item value is within a given range:$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()The whereIn method removes elements from the collection that do not have a specified item value that is contained within the given array:$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], ] */The whereIn 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. Use the whereInStrict method to filter using "strict" comparisons.whereInStrict()This method has the same signature as the whereIn method; however, all values are compared using "strict" comparisons.whereInstanceOf()The whereInstanceOf method filters the collection by a given class type: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()The whereNotBetween method filters the collection by determining if a specified item value is outside of a given range:$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()The whereNotIn method removes elements from the collection that have a specified item value that is contained within the given array:$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], ] */The whereNotIn 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. Use the whereNotInStrict method to filter using "strict" comparisons.whereNotInStrict()This method has the same signature as the whereNotIn method; however, all values are compared using "strict" comparisons.whereNotNull()The whereNotNull method returns items from the collection where the given key is not null:$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'], ]); $filtered = $collection->whereNotNull('name'); $filtered->all(); /* [ ['name' => 'Desk'], ['name' => 'Bookcase'], ] */whereNull()The whereNull method returns items from the collection where the given key is null:$collection = collect([ ['name' => 'Desk'], ['name' => null], ['name' => 'Bookcase'], ]); $filtered = $collection->whereNull('name'); $filtered->all(); /* [ ['name' => null], ] */wrap()The static wrap method wraps the given value in a collection when applicable: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()The zip method merges together the values of the given array with the values of the original collection at their corresponding index:$collection = collect(['Chair', 'Desk']); $zipped = $collection->zip([100, 200]); $zipped->all(); // [['Chair', 100], ['Desk', 200]]Lazy CollectionsIntroductionBefore learning more about Laravel's lazy collections, take some time to familiarize yourself with PHP generators.To supplement the already powerful Collection class, the LazyCollection class leverages PHP's generators to allow you to work with very large datasets while keeping memory usage low.For example, imagine your application needs to process a multi-gigabyte log file while taking advantage of Laravel's collection methods to parse the logs. Instead of reading the entire file into memory at once, lazy collections may be used to keep only a small part of the file in memory at a given time:use App\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... });Or, imagine you need to iterate through 10,000 Eloquent models. When using traditional Laravel collections, all 10,000 Eloquent models must be loaded into memory at the same time:use App\Models\User; $users = User::all()->filter(function ($user) { return $user->id > 500; });However, the query builder's cursor method returns a LazyCollection instance. This allows you to still only run a single query against the database but also only keep one Eloquent model loaded in memory at a time. In this example, the filter callback is not executed until we actually iterate over each user individually, allowing for a drastic reduction in memory usage:use App\Models\User; $users = User::cursor()->filter(function ($user) { return $user->id > 500; }); foreach ($users as $user) { echo $user->id; }Creating Lazy CollectionsTo create a lazy collection instance, you should pass a PHP generator function to the collection's make method:use Illuminate\Support\LazyCollection; LazyCollection::make(function () { $handle = fopen('log.txt', 'r'); while (($line = fgets($handle)) !== false) { yield $line; } });The Enumerable ContractAlmost all methods available on the Collection class are also available on the LazyCollection class. Both of these classes implement the Illuminate\Support\Enumerable contract, which defines the following methods:allaverageavgchunkchunkWhilecollapsecollectcombineconcatcontainscontainsStrictcountcountBycrossJoindddiffdiffAssocdiffKeysdumpduplicatesduplicatesStricteacheachSpreadeveryexceptfilterfirstfirstWhereflatMapflattenflipforPagegetgroupByhasimplodeintersectintersectByKeysisEmptyisNotEmptyjoinkeyBykeyslastmacromakemapmapIntomapSpreadmapToGroupsmapWithKeysmaxmedianmergemergeRecursiveminmodenthonlypadpartitionpipepluckrandomreducerejectreplacereplaceRecursivereversesearchshuffleskipslicesomesortsortBysortByDescsortKeyssortKeysDescsplitsumtaketaptimestoArraytoJsonunionuniqueuniqueStrictunlessunlessEmptyunlessNotEmptyunwrapvalueswhenwhenEmptywhenNotEmptywherewhereStrictwhereBetweenwhereInwhereInStrictwhereInstanceOfwhereNotBetweenwhereNotInwhereNotInStrictwrapzipMethods that mutate the collection (such as shift, pop, prepend etc.) are not available on the LazyCollection class.Lazy Collection MethodsIn addition to the methods defined in the Enumerable contract, the LazyCollection class contains the following methods:takeUntilTimeout()The takeUntilTimeout method returns a new lazy collection that will enumerate values until the specified time. After that time, the collection will then stop enumerating:$lazyCollection = LazyCollection::times(INF) ->takeUntilTimeout(now()->addMinute()); $lazyCollection->each(function ($number) { dump($number); sleep(1); }); // 1 // 2 // ... // 58 // 59To illustrate the usage of this method, imagine an application that submits invoices from the database using a cursor. You could define a scheduled task that runs every 15 minutes and only processes invoices for a maximum of 14 minutes: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()While the each method calls the given callback for each item in the collection right away, the tapEach method only calls the given callback as the items are being pulled out of the list one by one:// Nothing has been dumped so far... $lazyCollection = LazyCollection::times(INF)->tapEach(function ($value) { dump($value); }); // Three items are dumped... $array = $lazyCollection->take(3)->all(); // 1 // 2 // 3remember()The remember method returns a new lazy collection that will remember any values that have already been enumerated and will not retrieve them again on subsequent collection enumerations:// No query has been executed yet... $users = User::cursor()->remember(); // The query is executed... // The first 5 users are hydrated from the database... $users->take(5)->all(); // First 5 users come from the collection's cache... // The rest are hydrated from the database... $users->take(20)->all();
Eloquent: CollectionsIntroductionAll Eloquent methods that return more than one model result will return instances of the Illuminate\Database\Eloquent\Collection class, including results retrieved via the get method or accessed via a relationship. The Eloquent collection object extends Laravel's base collection, so it naturally inherits dozens of methods used to fluently work with the underlying array of Eloquent models. Be sure to review the Laravel collection documentation to learn all about these helpful methods!All collections also serve as iterators, allowing you to loop over them as if they were simple PHP arrays:use App\Models\User; $users = User::where('active', 1)->get(); foreach ($users as $user) { echo $user->name; }However, as previously mentioned, collections are much more powerful than arrays and expose a variety of map / reduce operations that may be chained using an intuitive interface. For example, we may remove all inactive models and then gather the first name for each remaining user:$names = User::all()->reject(function ($user) { return $user->active === false; })->map(function ($user) { return $user->name; });Eloquent Collection ConversionWhile most Eloquent collection methods return a new instance of an Eloquent collection, the collapse, flatten, flip, keys, pluck, and zip methods return a base collection instance. Likewise, if a map operation returns a collection that does not contain any Eloquent models, it will be converted to a base collection instance.Available MethodsAll Eloquent collections extend the base Laravel collection object; therefore, they inherit all of the powerful methods provided by the base collection class.In addition, the Illuminate\Database\Eloquent\Collection class provides a superset of methods to aid with managing your model collections. Most methods return Illuminate\Database\Eloquent\Collection instances; however, some methods, like modelKeys, return an Illuminate\Support\Collection instance.containsdiffexceptfindfreshintersectloadloadMissingmodelKeysmakeVisiblemakeHiddenonlytoQueryuniquecontains($key, $operator = null, $value = null)The contains method may be used to determine if a given model instance is contained by the collection. This method accepts a primary key or a model instance:$users->contains(1); $users->contains(User::find(1));diff($items)The diff method returns all of the models that are not present in the given collection:use App\Models\User; $users = $users->diff(User::whereIn('id', [1, 2, 3])->get());except($keys)The except method returns all of the models that do not have the given primary keys:$users = $users->except([1, 2, 3]);find($key)The find method returns the model that has a primary key matching the given key. If $key is a model instance, find will attempt to return a model matching the primary key. If $key is an array of keys, find will return all models which have a primary key in the given array:$users = User::all(); $user = $users->find(1);fresh($with = [\])The fresh method retrieves a fresh instance of each model in the collection from the database. In addition, any specified relationships will be eager loaded:$users = $users->fresh(); $users = $users->fresh('comments');intersect($items)The intersect method returns all of the models that are also present in the given collection:use App\Models\User; $users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());load($relations)The load method eager loads the given relationships for all models in the collection:$users->load(['comments', 'posts']); $users->load('comments.author');loadMissing($relations)The loadMissing method eager loads the given relationships for all models in the collection if the relationships are not already loaded:$users->loadMissing(['comments', 'posts']); $users->loadMissing('comments.author');modelKeys()The modelKeys method returns the primary keys for all models in the collection:$users->modelKeys(); // [1, 2, 3, 4, 5]makeVisible($attributes)The makeVisible method makes attributes visible that are typically "hidden" on each model in the collection:$users = $users->makeVisible(['address', 'phone_number']);makeHidden($attributes)The makeHidden method hides attributes that are typically "visible" on each model in the collection:$users = $users->makeHidden(['address', 'phone_number']);only($keys)The only method returns all of the models that have the given primary keys:$users = $users->only([1, 2, 3]);toQuery()The toQuery method returns an Eloquent query builder instance containing a whereIn constraint on the collection model's primary keys:use App\Models\User; $users = User::where('status', 'VIP')->get(); $users->toQuery()->update([ 'status' => 'Administrator', ]);unique($key = null, $strict = false)The unique method returns all of the unique models in the collection. Any models of the same type with the same primary key as another model in the collection are removed:$users = $users->unique();Custom CollectionsIf you would like to use a custom Collection object when interacting with a given model, you may define a newCollection method on your model:<?php namespace App\Models; use App\Support\UserCollection; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Create a new Eloquent Collection instance. * * @param array $models * @return \Illuminate\Database\Eloquent\Collection */ public function newCollection(array $models = []) { return new UserCollection($models); } }Once you have defined a newCollection method, you will receive an instance of your custom collection anytime Eloquent would normally return an Illuminate\Database\Eloquent\Collection instance. If you would like to use a custom collection for every model in your application, you should define the newCollection method on a base model class that is extended by all of your application's models.
Eloquent: Getting StartedIntroductionLaravel includes Eloquent, an object-relational mapper (ORM) that makes it enjoyable to interact with your database. When using Eloquent, each database table has a corresponding "Model" that is used to interact with that table. In addition to retrieving records from the database table, Eloquent models allow you to insert, update, and delete records from the table as well.Before getting started, be sure to configure a database connection in your application's config/database.php configuration file. For more information on configuring your database, check out the database configuration documentation.Generating Model ClassesTo get started, let's create an Eloquent model. Models typically live in the app\Models directory and extend the Illuminate\Database\Eloquent\Model class. You may use the make:model Artisan command to generate a new model:php artisan make:model FlightIf you would like to generate a database migration when you generate the model, you may use the --migration or -m option:php artisan make:model Flight --migrationYou may generate various other types of classes when generating a model, such as factories, seeders, policies, controllers, and form requests. In addition, these options may be combined to create multiple classes at once:# Generate a model and a FlightFactory class... php artisan make:model Flight --factory php artisan make:model Flight -f # Generate a model and a FlightSeeder class... php artisan make:model Flight --seed php artisan make:model Flight -s # Generate a model and a FlightController class... php artisan make:model Flight --controller php artisan make:model Flight -c # Generate a model, FlightController resource class, and form request classes... php artisan make:model Flight --controller --resource --requests php artisan make:model Flight -crR # Generate a model and a FlightPolicy class... php artisan make:model Flight --policy # Generate a model and a migration, factory, seeder, and controller... php artisan make:model Flight -mfsc # Shortcut to generate a model, migration, factory, seeder, policy, controller, and form requests... php artisan make:model Flight --all # Generate a pivot model... php artisan make:model Member --pivotEloquent Model ConventionsModels generated by the make:model command will be placed in the app/Models directory. Let's examine a basic model class and discuss some of Eloquent's key conventions:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { // }Table NamesAfter glancing at the example above, you may have noticed that we did not tell Eloquent which database table corresponds to our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table, while an AirTrafficController model would store records in an air_traffic_controllers table.If your model's corresponding database table does not fit this convention, you may manually specify the model's table name by defining a table property on the model:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The table associated with the model. * * @var string */ protected $table = 'my_flights'; }Primary KeysEloquent will also assume that each model's corresponding database table has a primary key column named id. If necessary, you may define a protected $primaryKey property on your model to specify a different column that serves as your model's primary key:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The primary key associated with the table. * * @var string */ protected $primaryKey = 'flight_id'; }In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that Eloquent will automatically cast the primary key to an integer. If you wish to use a non-incrementing or a non-numeric primary key you must define a public $incrementing property on your model that is set to false:<?php class Flight extends Model { /** * Indicates if the model's ID is auto-incrementing. * * @var bool */ public $incrementing = false; }If your model's primary key is not an integer, you should define a protected $keyType property on your model. This property should have a value of string:<?php class Flight extends Model { /** * The data type of the auto-incrementing ID. * * @var string */ protected $keyType = 'string'; }"Composite" Primary KeysEloquent requires each model to have at least one uniquely identifying "ID" that can serve as its primary key. "Composite" primary keys are not supported by Eloquent models. However, you are free to add additional multi-column, unique indexes to your database tables in addition to the table's uniquely identifying primary key.TimestampsBy default, Eloquent expects created_at and updated_at columns to exist on your model's corresponding database table. Eloquent will automatically set these column's values when models are created or updated. If you do not want these columns to be automatically managed by Eloquent, you should define a $timestamps property on your model with a value of false:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * Indicates if the model should be timestamped. * * @var bool */ public $timestamps = false; }If you need to customize the format of your model's timestamps, set the $dateFormat property on your model. This property determines how date attributes are stored in the database as well as their format when the model is serialized to an array or JSON:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The storage format of the model's date columns. * * @var string */ protected $dateFormat = 'U'; }If you need to customize the names of the columns used to store the timestamps, you may define CREATED_AT and UPDATED_AT constants on your model:<?php class Flight extends Model { const CREATED_AT = 'creation_date'; const UPDATED_AT = 'updated_date'; }Database ConnectionsBy default, all Eloquent models will use the default database connection that is configured for your application. If you would like to specify a different connection that should be used when interacting with a particular model, you should define a $connection property on the model:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The database connection that should be used by the model. * * @var string */ protected $connection = 'sqlite'; }Default Attribute ValuesBy default, a newly instantiated model instance will not contain any attribute values. If you would like to define the default values for some of your model's attributes, you may define an $attributes property on your model:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The model's default values for attributes. * * @var array */ protected $attributes = [ 'delayed' => false, ]; }Retrieving ModelsOnce you have created a model and its associated database table, you are ready to start retrieving data from your database. You can think of each Eloquent model as a powerful query builder allowing you to fluently query the database table associated with the model. The model's all method will retrieve all of the records from the model's associated database table:use App\Models\Flight; foreach (Flight::all() as $flight) { echo $flight->name; }Building QueriesThe Eloquent all method will return all of the results in the model's table. However, since each Eloquent model serves as a query builder, you may add additional constraints to queries and then invoke the get method to retrieve the results:$flights = Flight::where('active', 1) ->orderBy('name') ->take(10) ->get();Since Eloquent models are query builders, you should review all of the methods provided by Laravel's query builder. You may use any of these methods when writing your Eloquent queries.Refreshing ModelsIf you already have an instance of an Eloquent model that was retrieved from the database, you can "refresh" the model using the fresh and refresh methods. The fresh method will re-retrieve the model from the database. The existing model instance will not be affected:$flight = Flight::where('number', 'FR 900')->first(); $freshFlight = $flight->fresh();The refresh method will re-hydrate the existing model using fresh data from the database. In addition, all of its loaded relationships will be refreshed as well:$flight = Flight::where('number', 'FR 900')->first(); $flight->number = 'FR 456'; $flight->refresh(); $flight->number; // "FR 900"CollectionsAs we have seen, Eloquent methods like all and get retrieve multiple records from the database. However, these methods don't return a plain PHP array. Instead, an instance of Illuminate\Database\Eloquent\Collection is returned.The Eloquent Collection class extends Laravel's base Illuminate\Support\Collection class, which provides a variety of helpful methods for interacting with data collections. For example, the reject method may be used to remove models from a collection based on the results of an invoked closure:$flights = Flight::where('destination', 'Paris')->get(); $flights = $flights->reject(function ($flight) { return $flight->cancelled; });In addition to the methods provided by Laravel's base collection class, the Eloquent collection class provides a few extra methods that are specifically intended for interacting with collections of Eloquent models.Since all of Laravel's collections implement PHP's iterable interfaces, you may loop over collections as if they were an array:foreach ($flights as $flight) { echo $flight->name; }Chunking ResultsYour application may run out of memory if you attempt to load tens of thousands of Eloquent records via the all or get methods. Instead of using these methods, the chunk method may be used to process large numbers of models more efficiently.The chunk method will retrieve a subset of Eloquent models, passing them to a closure for processing. Since only the current chunk of Eloquent models is retrieved at a time, the chunk method will provide significantly reduced memory usage when working with a large number of models:use App\Models\Flight; Flight::chunk(200, function ($flights) { foreach ($flights as $flight) { // } });The first argument passed to the chunk method is the number of records you wish to receive per "chunk". The closure passed as the second argument will be invoked for each chunk that is retrieved from the database. A database query will be executed to retrieve each chunk of records passed to the closure.If you are filtering the results of the chunk method based on a column that you will also be updating while iterating over the results, you should use the chunkById method. Using the chunk method in these scenarios could lead to unexpected and inconsistent results. Internally, the chunkById method will always retrieve models with an id column greater than the last model in the previous chunk:Flight::where('departed', true) ->chunkById(200, function ($flights) { $flights->each->update(['departed' => false]); }, $column = 'id');Streaming Results LazilyThe lazy method works similarly to the chunk method in the sense that, behind the scenes, it executes the query in chunks. However, instead of passing each chunk directly into a callback as is, the lazy method returns a flattened LazyCollection of Eloquent models, which lets you interact with the results as a single stream:use App\Models\Flight; foreach (Flight::lazy() as $flight) { // }If you are filtering the results of the lazy method based on a column that you will also be updating while iterating over the results, you should use the lazyById method. Internally, the lazyById method will always retrieve models with an id column greater than the last model in the previous chunk:Flight::where('departed', true) ->lazyById(200, $column = 'id') ->each->update(['departed' => false]);You may filter the results based on the descending order of the id using the lazyByIdDesc method.CursorsSimilar to the lazy method, the cursor method may be used to significantly reduce your application's memory consumption when iterating through tens of thousands of Eloquent model records.The cursor method will only execute a single database query; however, the individual Eloquent models will not be hydrated until they are actually iterated over. Therefore, only one Eloquent model is kept in memory at any given time while iterating over the cursor.Since the cursor method only ever holds a single Eloquent model in memory at a time, it cannot eager load relationships. If you need to eager load relationships, consider using the lazy method instead.Internally, the cursor method uses PHP generators to implement this functionality:use App\Models\Flight; foreach (Flight::where('destination', 'Zurich')->cursor() as $flight) { // }The cursor returns an Illuminate\Support\LazyCollection instance. Lazy collections allow you to use many of the collection methods available on typical Laravel collections while only loading a single model into memory at a time:use App\Models\User; $users = User::cursor()->filter(function ($user) { return $user->id > 500; }); foreach ($users as $user) { echo $user->id; }Although the cursor method uses far less memory than a regular query (by only holding a single Eloquent model in memory at a time), it will still eventually run out of memory. This is due to PHP's PDO driver internally caching all raw query results in its buffer. If you're dealing with a very large number of Eloquent records, consider using the lazy method instead.Advanced SubqueriesSubquery SelectsEloquent also offers advanced subquery support, which allows you to pull information from related tables in a single query. For example, let's imagine that we have a table of flight destinations and a table of flights to destinations. The flights table contains an arrived_at column which indicates when the flight arrived at the destination.Using the subquery functionality available to the query builder's select and addSelect methods, we can select all of the destinations and the name of the flight that most recently arrived at that destination using a single query:use App\Models\Destination; use App\Models\Flight; return Destination::addSelect(['last_flight' => Flight::select('name') ->whereColumn('destination_id', 'destinations.id') ->orderByDesc('arrived_at') ->limit(1) ])->get();Subquery OrderingIn addition, the query builder's orderBy function supports subqueries. Continuing to use our flight example, we may use this functionality to sort all destinations based on when the last flight arrived at that destination. Again, this may be done while executing a single database query:return Destination::orderByDesc( Flight::select('arrived_at') ->whereColumn('destination_id', 'destinations.id') ->orderByDesc('arrived_at') ->limit(1) )->get();Retrieving Single Models / AggregatesIn addition to retrieving all of the records matching a given query, you may also retrieve single records using the find, first, or firstWhere methods. Instead of returning a collection of models, these methods return a single model instance:use App\Models\Flight; // Retrieve a model by its primary key... $flight = Flight::find(1); // Retrieve the first model matching the query constraints... $flight = Flight::where('active', 1)->first(); // Alternative to retrieving the first model matching the query constraints... $flight = Flight::firstWhere('active', 1);Sometimes you may wish to retrieve the first result of a query or perform some other action if no results are found. The firstOr method will return the first result matching the query or, if no results are found, execute the given closure. The value returned by the closure will be considered the result of the firstOr method:$model = Flight::where('legs', '>', 3)->firstOr(function () { // ... });Not Found ExceptionsSometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The findOrFail and firstOrFail methods will retrieve the first result of the query; however, if no result is found, an Illuminate\Database\Eloquent\ModelNotFoundException will be thrown:$flight = Flight::findOrFail(1); $flight = Flight::where('legs', '>', 3)->firstOrFail();If the ModelNotFoundException is not caught, a 404 HTTP response is automatically sent back to the client:use App\Models\Flight; Route::get('/api/flights/{id}', function ($id) { return Flight::findOrFail($id); });Retrieving Or Creating ModelsThe firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes resulting from merging the first array argument with the optional second array argument:The firstOrNew method, like firstOrCreate, will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to manually call the save method to persist it:use App\Models\Flight; // Retrieve flight by name or create it if it doesn't exist... $flight = Flight::firstOrCreate([ 'name' => 'London to Paris' ]); // Retrieve flight by name or create it with the name, delayed, and arrival_time attributes... $flight = Flight::firstOrCreate( ['name' => 'London to Paris'], ['delayed' => 1, 'arrival_time' => '11:30'] ); // Retrieve flight by name or instantiate a new Flight instance... $flight = Flight::firstOrNew([ 'name' => 'London to Paris' ]); // Retrieve flight by name or instantiate with the name, delayed, and arrival_time attributes... $flight = Flight::firstOrNew( ['name' => 'Tokyo to Sydney'], ['delayed' => 1, 'arrival_time' => '11:30'] );Retrieving AggregatesWhen interacting with Eloquent models, you may also use the count, sum, max, and other aggregate methods provided by the Laravel query builder. As you might expect, these methods return a scalar value instead of an Eloquent model instance:$count = Flight::where('active', 1)->count(); $max = Flight::where('active', 1)->max('price');Inserting & Updating ModelsInsertsOf course, when using Eloquent, we don't only need to retrieve models from the database. We also need to insert new records. Thankfully, Eloquent makes it simple. To insert a new record into the database, you should instantiate a new model instance and set attributes on the model. Then, call the save method on the model instance:<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Models\Flight; use Illuminate\Http\Request; class FlightController extends Controller { /** * Store a new flight in the database. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { // Validate the request... $flight = new Flight; $flight->name = $request->name; $flight->save(); } }In this example, we assign the name field from the incoming HTTP request to the name attribute of the App\Models\Flight model instance. When we call the save method, a record will be inserted into the database. The model's created_at and updated_at timestamps will automatically be set when the save method is called, so there is no need to set them manually.Alternatively, you may use the create method to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the create method:use App\Models\Flight; $flight = Flight::create([ 'name' => 'London to Paris', ]);However, before using the create method, you will need to specify either a fillable or guarded property on your model class. These properties are required because all Eloquent models are protected against mass assignment vulnerabilities by default. To learn more about mass assignment, please consult the mass assignment documentation.UpdatesThe save method may also be used to update models that already exist in the database. To update a model, you should retrieve it and set any attributes you wish to update. Then, you should call the model's save method. Again, the updated_at timestamp will automatically be updated, so there is no need to manually set its value:use App\Models\Flight; $flight = Flight::find(1); $flight->name = 'Paris to London'; $flight->save();Mass UpdatesUpdates can also be performed against models that match a given query. In this example, all flights that are active and have a destination of San Diego will be marked as delayed:Flight::where('active', 1) ->where('destination', 'San Diego') ->update(['delayed' => 1]);The update method expects an array of column and value pairs representing the columns that should be updated. The update method returns the number of affected rows.When issuing a mass update via Eloquent, the saving, saved, updating, and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.Examining Attribute ChangesEloquent provides the isDirty, isClean, and wasChanged methods to examine the internal state of your model and determine how its attributes have changed from when the model was originally retrieved.The isDirty method determines if any of the model's attributes have been changed since the model was retrieved. You may pass a specific attribute name to the isDirty method to determine if a particular attribute is dirty. The isClean will determine if an attribute has remained unchanged since the model was retrieved. This method also accepts an optional attribute argument:use App\Models\User; $user = User::create([ 'first_name' => 'Taylor', 'last_name' => 'Otwell', 'title' => 'Developer', ]); $user->title = 'Painter'; $user->isDirty(); // true $user->isDirty('title'); // true $user->isDirty('first_name'); // false $user->isClean(); // false $user->isClean('title'); // false $user->isClean('first_name'); // true $user->save(); $user->isDirty(); // false $user->isClean(); // trueThe wasChanged method determines if any attributes were changed when the model was last saved within the current request cycle. If needed, you may pass an attribute name to see if a particular attribute was changed:$user = User::create([ 'first_name' => 'Taylor', 'last_name' => 'Otwell', 'title' => 'Developer', ]); $user->title = 'Painter'; $user->save(); $user->wasChanged(); // true $user->wasChanged('title'); // true $user->wasChanged('first_name'); // falseThe getOriginal method returns an array containing the original attributes of the model regardless of any changes to the model since it was retrieved. If needed, you may pass a specific attribute name to get the original value of a particular attribute:$user = User::find(1); $user->name; // John $user->email; // john@example.com $user->name = "Jack"; $user->name; // Jack $user->getOriginal('name'); // John $user->getOriginal(); // Array of original attributes...Mass AssignmentYou may use the create method to "save" a new model using a single PHP statement. The inserted model instance will be returned to you by the method:use App\Models\Flight; $flight = Flight::create([ 'name' => 'London to Paris', ]);However, before using the create method, you will need to specify either a fillable or guarded property on your model class. These properties are required because all Eloquent models are protected against mass assignment vulnerabilities by default.A mass assignment vulnerability occurs when a user passes an unexpected HTTP request field and that field changes a column in your database that you did not expect. For example, a malicious user might send an is_admin parameter through an HTTP request, which is then passed to your model's create method, allowing the user to escalate themselves to an administrator.So, to get started, you should define which model attributes you want to make mass assignable. You may do this using the $fillable property on the model. For example, let's make the name attribute of our Flight model mass assignable:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Flight extends Model { /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['name']; }Once you have specified which attributes are mass assignable, you may use the create method to insert a new record in the database. The create method returns the newly created model instance:$flight = Flight::create(['name' => 'London to Paris']);If you already have a model instance, you may use the fill method to populate it with an array of attributes:$flight->fill(['name' => 'Amsterdam to Frankfurt']);Mass Assignment & JSON ColumnsWhen assigning JSON columns, each column's mass assignable key must be specified in your model's $fillable array. For security, Laravel does not support updating nested JSON attributes when using the guarded property:/** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'options->enabled', ];Allowing Mass AssignmentIf you would like to make all of your attributes mass assignable, you may define your model's $guarded property as an empty array. If you choose to unguard your model, you should take special care to always hand-craft the arrays passed to Eloquent's fill, create, and update methods:/** * The attributes that aren't mass assignable. * * @var array */ protected $guarded = [];UpsertsOccasionally, you may need to update an existing model or create a new model if no matching model exists. Like the firstOrCreate method, the updateOrCreate method persists the model, so there's no need to manually call the save method.In the example below, if a flight exists with a departure location of Oakland and a destination location of San Diego, its price and discounted columns will be updated. If no such flight exists, a new flight will be created which has the attributes resulting from merging the first argument array with the second argument array:$flight = Flight::updateOrCreate( ['departure' => 'Oakland', 'destination' => 'San Diego'], ['price' => 99, 'discounted' => 1] );If you would like to perform multiple "upserts" in a single query, then you should use the upsert method instead. The method's first argument consists of the values to insert or update, while the second argument lists the column(s) that uniquely identify records within the associated table. The method's third and final argument is an array of the columns that should be updated if a matching record already exists in the database. The upsert method will automatically set the created_at and updated_at timestamps if timestamps are enabled on the model:Flight::upsert([ ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150] ], ['departure', 'destination'], ['price']);Deleting ModelsTo delete a model, you may call the delete method on the model instance:use App\Models\Flight; $flight = Flight::find(1); $flight->delete();You may call the truncate method to delete all of the model's associated database records. The truncate operation will also reset any auto-incrementing IDs on the model's associated table:Flight::truncate();Deleting An Existing Model By Its Primary KeyIn the example above, we are retrieving the model from the database before calling the delete method. However, if you know the primary key of the model, you may delete the model without explicitly retrieving it by calling the destroy method. In addition to accepting the single primary key, the destroy method will accept multiple primary keys, an array of primary keys, or a collection of primary keys:Flight::destroy(1); Flight::destroy(1, 2, 3); Flight::destroy([1, 2, 3]); Flight::destroy(collect([1, 2, 3]));The destroy method loads each model individually and calls the delete method so that the deleting and deleted events are properly dispatched for each model.Deleting Models Using QueriesOf course, you may build an Eloquent query to delete all models matching your query's criteria. In this example, we will delete all flights that are marked as inactive. Like mass updates, mass deletes will not dispatch model events for the models that are deleted:$deleted = Flight::where('active', 0)->delete();When executing a mass delete statement via Eloquent, the deleting and deleted model events will not be dispatched for the deleted models. This is because the models are never actually retrieved when executing the delete statement.Soft DeletingIn addition to actually removing records from your database, Eloquent can also "soft delete" models. When models are soft deleted, they are not actually removed from your database. Instead, a deleted_at attribute is set on the model indicating the date and time at which the model was "deleted". To enable soft deletes for a model, add the Illuminate\Database\Eloquent\SoftDeletes trait to the model:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Flight extends Model { use SoftDeletes; }The SoftDeletes trait will automatically cast the deleted_at attribute to a DateTime / Carbon instance for you.You should also add the deleted_at column to your database table. The Laravel schema builder contains a helper method to create this column:use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('flights', function (Blueprint $table) { $table->softDeletes(); }); Schema::table('flights', function (Blueprint $table) { $table->dropSoftDeletes(); });Now, when you call the delete method on the model, the deleted_at column will be set to the current date and time. However, the model's database record will be left in the table. When querying a model that uses soft deletes, the soft deleted models will automatically be excluded from all query results.To determine if a given model instance has been soft deleted, you may use the trashed method:if ($flight->trashed()) { // }Restoring Soft Deleted ModelsSometimes you may wish to "un-delete" a soft deleted model. To restore a soft deleted model, you may call the restore method on a model instance. The restore method will set the model's deleted_at column to null:$flight->restore();You may also use the restore method in a query to restore multiple models. Again, like other "mass" operations, this will not dispatch any model events for the models that are restored:Flight::withTrashed() ->where('airline_id', 1) ->restore();The restore method may also be used when building relationship queries:$flight->history()->restore();Permanently Deleting ModelsSometimes you may need to truly remove a model from your database. You may use the forceDelete method to permanently remove a soft deleted model from the database table:$flight->forceDelete();You may also use the forceDelete method when building Eloquent relationship queries:$flight->history()->forceDelete();Querying Soft Deleted ModelsIncluding Soft Deleted ModelsAs noted above, soft deleted models will automatically be excluded from query results. However, you may force soft deleted models to be included in a query's results by calling the withTrashed method on the query:use App\Models\Flight; $flights = Flight::withTrashed() ->where('account_id', 1) ->get();The withTrashed method may also be called when building a relationship query:$flight->history()->withTrashed()->get();Retrieving Only Soft Deleted ModelsThe onlyTrashed method will retrieve only soft deleted models:$flights = Flight::onlyTrashed() ->where('airline_id', 1) ->get();Pruning ModelsSometimes you may want to periodically delete models that are no longer needed. To accomplish this, you may add the Illuminate\Database\Eloquent\Prunable or Illuminate\Database\Eloquent\MassPrunable trait to the models you would like to periodically prune. After adding one of the traits to the model, implement a prunable method which returns an Eloquent query builder that resolves the models that are no longer needed:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Prunable; class Flight extends Model { use Prunable; /** * Get the prunable model query. * * @return \Illuminate\Database\Eloquent\Builder */ public function prunable() { return static::where('created_at', '<=', now()->subMonth()); } }When marking models as Prunable, you may also define a pruning method on the model. This method will be called before the model is deleted. This method can be useful for deleting any additional resources associated with the model, such as stored files, before the model is permanently removed from the database:/** * Prepare the model for pruning. * * @return void */ protected function pruning() { // }After configuring your prunable model, you should schedule the model:prune Artisan command in your application's App\Console\Kernel class. You are free to choose the appropriate interval at which this command should be run:/** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('model:prune')->daily(); }Behind the scenes, the model:prune command will automatically detect "Prunable" models within your application's app/Models directory. If your models are in a different location, you may use the --model option to specify the model class names:$schedule->command('model:prune', [ '--model' => [Address::class, Flight::class], ])->daily();If you wish to exclude certain models from being pruned while pruning all other detected models, you may use the --except option:$schedule->command('model:prune', [ '--except' => [Address::class, Flight::class], ])->daily();You may test your prunable query by executing the model:prune command with the --pretend option. When pretending, the model:prune command will simply report how many records would be pruned if the command were to actually run:php artisan model:prune --pretendSoft deleting models will be permanently deleted (forceDelete) if they match the prunable query.Mass PruningWhen models are marked with the Illuminate\Database\Eloquent\MassPrunable trait, models are deleted from the database using mass-deletion queries. Therefore, the pruning method will not be invoked, nor will the deleting and deleted model events be dispatched. This is because the models are never actually retrieved before deletion, thus making the pruning process much more efficient:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\MassPrunable; class Flight extends Model { use MassPrunable; /** * Get the prunable model query. * * @return \Illuminate\Database\Eloquent\Builder */ public function prunable() { return static::where('created_at', '<=', now()->subMonth()); } }Replicating ModelsYou may create an unsaved copy of an existing model instance using the replicate method. This method is particularly useful when you have model instances that share many of the same ..:use App\Models\Address; $shipping = Address::create([ 'type' => 'shipping', 'line_1' => '123 Example Street', 'city' => 'Victorville', 'state' => 'CA', 'postcode' => '90001', ]); $billing = $shipping->replicate()->fill([ 'type' => 'billing' ]); $billing->save();To exclude one or more attributes from being replicated to the new model, you may pass an array to the replicate method:$flight = Flight::create([ 'destination' => 'LAX', 'origin' => 'LHR', 'last_flown' => '2020-03-04 11:00:00', 'last_pilot_id' => 747, ]); $flight = $flight->replicate([ 'last_flown', 'last_pilot_id' ]);Query ScopesGlobal ScopesGlobal scopes allow you to add constraints to all queries for a given model. Laravel's own soft delete functionality utilizes global scopes to only retrieve "non-deleted" models from the database. Writing your own global scopes can provide a convenient, easy way to make sure every query for a given model receives certain constraints.Writing Global ScopesWriting a global scope is simple. First, define a class that implements the Illuminate\Database\Eloquent\Scope interface. Laravel does not have a conventional location where you should place scope classes, so you are free to place this class in any directory that you wish.The Scope interface requires you to implement one method: apply. The apply method may add where constraints or other types of clauses to the query as needed:<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; class AncientScope implements Scope { /** * Apply the scope to a given Eloquent query builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */ public function apply(Builder $builder, Model $model) { $builder->where('created_at', '<', now()->subYears(2000)); } }If your global scope is adding columns to the select clause of the query, you should use the addSelect method instead of select. This will prevent the unintentional replacement of the query's existing select clause.Applying Global ScopesTo assign a global scope to a model, you should override the model's booted method and invoke the model's addGlobalScope method. The addGlobalScope method accepts an instance of your scope as its only argument:<?php namespace App\Models; use App\Scopes\AncientScope; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * The "booted" method of the model. * * @return void */ protected static function booted() { static::addGlobalScope(new AncientScope); } }After adding the scope in the example above to the App\Models\User model, a call to the User::all() method will execute the following SQL query:select * from `users` where `created_at` < 0021-02-18 00:00:00Anonymous Global ScopesEloquent also allows you to define global scopes using closures, which is particularly useful for simple scopes that do not warrant a separate class of their own. When defining a global scope using a closure, you should provide a scope name of your own choosing as the first argument to the addGlobalScope method:<?php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * The "booted" method of the model. * * @return void */ protected static function booted() { static::addGlobalScope('ancient', function (Builder $builder) { $builder->where('created_at', '<', now()->subYears(2000)); }); } }Removing Global ScopesIf you would like to remove a global scope for a given query, you may use the withoutGlobalScope method. This method accepts the class name of the global scope as its only argument:User::withoutGlobalScope(AncientScope::class)->get();Or, if you defined the global scope using a closure, you should pass the string name that you assigned to the global scope:User::withoutGlobalScope('ancient')->get();If you would like to remove several or even all of the query's global scopes, you may use the withoutGlobalScopes method:// Remove all of the global scopes... User::withoutGlobalScopes()->get(); // Remove some of the global scopes... User::withoutGlobalScopes([ FirstScope::class, SecondScope::class ])->get();Local ScopesLocal scopes allow you to define common sets of query constraints that you may easily re-use throughout your application. For example, you may need to frequently retrieve all users that are considered "popular". To define a scope, prefix an Eloquent model method with scope.Scopes should always return the same query builder instance or void:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Scope a query to only include popular users. * * @param \Illuminate\Database\Eloquent\Builder $query * @return \Illuminate\Database\Eloquent\Builder */ public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * Scope a query to only include active users. * * @param \Illuminate\Database\Eloquent\Builder $query * @return void */ public function scopeActive($query) { $query->where('active', 1); } }Utilizing A Local ScopeOnce the scope has been defined, you may call the scope methods when querying the model. However, you should not include the scope prefix when calling the method. You can even chain calls to various scopes:use App\Models\User; $users = User::popular()->active()->orderBy('created_at')->get();Combining multiple Eloquent model scopes via an or query operator may require the use of closures to achieve the correct logical grouping:$users = User::popular()->orWhere(function (Builder $query) { $query->active(); })->get();However, since this can be cumbersome, Laravel provides a "higher order" orWhere method that allows you to fluently chain scopes together without the use of closures:$users = App\Models\User::popular()->orWhere->active()->get();Dynamic ScopesSometimes you may wish to define a scope that accepts parameters. To get started, just add your additional parameters to your scope method's signature. Scope parameters should be defined after the $query parameter:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Scope a query to only include users of a given type. * * @param \Illuminate\Database\Eloquent\Builder $query * @param mixed $type * @return \Illuminate\Database\Eloquent\Builder */ public function scopeOfType($query, $type) { return $query->where('type', $type); } }Once the expected arguments have been added to your scope method's signature, you may pass the arguments when calling the scope:$users = User::ofType('admin')->get();Comparing ModelsSometimes you may need to determine if two models are the "same" or not. The is and isNot methods may be used to quickly verify two models have the same primary key, table, and database connection or not:if ($post->is($anotherPost)) { // } if ($post->isNot($anotherPost)) { // }The is and isNot methods are also available when using the belongsTo, hasOne, morphTo, and morphOne relationships. This method is particularly helpful when you would like to compare a related model without issuing a query to retrieve that model:if ($post->author()->is($user)) { // }EventsWant to broadcast your Eloquent events directly to your client-side application? Check out Laravel's model event broadcasting.Eloquent models dispatch several events, allowing you to hook into the following moments in a model's lifecycle: retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored, and replicating.The retrieved event will dispatch when an existing model is retrieved from the database. When a new model is saved for the first time, the creating and created events will dispatch. The updating / updated events will dispatch when an existing model is modified and the save method is called. The saving / saved events will dispatch when a model is created or updated - even if the model's attributes have not been changed. Event names ending with -ing are dispatched before any changes to the model are persisted, while events ending with -ed are dispatched after the changes to the model are persisted.To start listening to model events, define a $dispatchesEvents property on your Eloquent model. This property maps various points of the Eloquent model's lifecycle to your own event classes. Each model event class should expect to receive an instance of the affected model via its constructor:<?php namespace App\Models; use App\Events\UserDeleted; use App\Events\UserSaved; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The event map for the model. * * @var array */ protected $dispatchesEvents = [ 'saved' => UserSaved::class, 'deleted' => UserDeleted::class, ]; }After defining and mapping your Eloquent events, you may use event listeners to handle the events.When issuing a mass update or delete query via Eloquent, the saved, updated, deleting, and deleted model events will not be dispatched for the affected models. This is because the models are never actually retrieved when performing mass updates or deletes.Using ClosuresInstead of using custom event classes, you may register closures that execute when various model events are dispatched. Typically, you should register these closures in the booted method of your model:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * The "booted" method of the model. * * @return void */ protected static function booted() { static::created(function ($user) { // }); } }If needed, you may utilize queueable anonymous event listeners when registering model events. This will instruct Laravel to execute the model event listener in the background using your application's queue:use function Illuminate\Events\queueable; static::created(queueable(function ($user) { // }));ObserversDefining ObserversIf you are listening for many events on a given model, you may use observers to group all of your listeners into a single 60 lass. Observer classes have method names which reflect the Eloquent events you wish to listen for. Each of these methods receives the affected model as their only argument. The make:observer Artisan command is the easiest way to create a new observer class:php artisan make:observer UserObserver --model=UserThis command will place the new observer in your App/Observers directory. If this directory does not exist, Artisan will create it for you. Your fresh observer will look like the following:<?php namespace App\Observers; use App\Models\User; class UserObserver { /** * Handle the User "created" event. * * @param \App\Models\User $user * @return void */ public function created(User $user) { // } /** * Handle the User "updated" event. * * @param \App\Models\User $user * @return void */ public function updated(User $user) { // } /** * Handle the User "deleted" event. * * @param \App\Models\User $user * @return void */ public function deleted(User $user) { // } /** * Handle the User "forceDeleted" event. * * @param \App\Models\User $user * @return void */ public function forceDeleted(User $user) { // } }To register an observer, you need to call the observe method on the model you wish to observe. You may register observers in the boot method of your application's App\Providers\EventServiceProvider service provider:use App\Models\User; use App\Observers\UserObserver; /** * Register any events for your application. * * @return void */ public function boot() { User::observe(UserObserver::class); }There are additional events an observer can listen to, such as saving and retrieved. These events are described within the events documentation.Observers & Database TransactionsWhen models are being created within a database transaction, you may want to instruct an observer to only execute its event handlers after the database transaction is committed. You may accomplish this by defining an $afterCommit property on the observer. If a database transaction is not in progress, the event handlers will execute immediately:<?php namespace App\Observers; use App\Models\User; class UserObserver { /** * Handle events after all transactions are committed. * * @var bool */ public $afterCommit = true; /** * Handle the User "created" event. * * @param \App\Models\User $user * @return void */ public function created(User $user) { // } }Muting EventsYou may occasionally need to temporarily "mute" all events fired by a model. You may achieve this using the withoutEvents method. The withoutEvents method accepts a closure as its only argument. Any code executed within this closure will not dispatch model events, and any value returned by the closure will be returned by the withoutEvents method:use App\Models\User; $user = User::withoutEvents(function () use () { User::findOrFail(1)->delete(); return User::find(2); });Saving A Single Model Without EventsSometimes you may wish to "save" a given model without dispatching any events. You may accomplish this using the saveQuietly method:$user = User::findOrFail(1); $user->name = 'Victoria Faith'; $user->saveQuietly();