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();
## [Illuminate Database](https://github.com/illuminate/database/tree/master) The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style ORM, and schema builder. It currently supports MySQL, Postgres, SQL Server, and SQLite. It also serves as the database layer of the Laravel PHP framework. ### Usage Instructions First, create a new "Capsule" manager instance. Capsule aims to make configuring the library for usage outside of the Laravel framework as easy as possible.use Illuminate\Database\Capsule\Manager as Capsule;$capsule = new Capsule;$capsule->addConnection(['driver' => 'mysql','host' => 'localhost','database' => 'database','username' => 'root','password' => 'password','charset' => 'utf8','collation' => 'utf8_unicode_ci','prefix' => '',]);// Setup the Eloquent ORM... (optional)$capsule->bootEloquent();// Set the event dispatcher used by Eloquent models... (optional)$capsule->setEventDispatcher(...);// Set the cache manager instance used by connections... (optional)$capsule->setCacheManager(...);// Make this Capsule instance available globally via static methods... (optional)$capsule->setAsGlobal(); Once the Capsule instance has been registered. You may use it like so: **Using The Query Builder** $users = Capsule::table('users')->where('votes', '>' 100)->get(); Other core methods may be accessed directly from the Capsule in the same manner as from the DB facade: $results = Capsule::select('select * from users where id = ?', array(1)); **Using The Schema Builder** Capsule::schema()->create('users', function($table){$table->increments('id');$table->string('email')->unique();$table->timestamps();}); **Using The Eloquent ORM** class User extends Illuminate\Database\Eloquent\Model {}$users = User::where('votes', '>', 1)->get();
IntroductionLaravel's database query builder provides a convenient, fluent interface to creating and running database queries. It can be used to perform most database operations in your application and works perfectly with all of Laravel's supported database systems.The Laravel query builder uses PDO parameter binding to protect your application against SQL injection attacks. There is no need to clean or sanitize strings passed to the query builder as query bindings.PDO does not support binding column names. Therefore, you should never allow user input to dictate the column names referenced by your queries, including "order by" columns.Running Database QueriesRetrieving All Rows From A TableYou may use the table method provided by the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally retrieve the results of the query using the get method:<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\DB; class UserController extends Controller { /** * Show a list of all of the application's users. * * @return \Illuminate\Http\Response */ public function index() { $users = DB::table('users')->get(); return view('user.index', ['users' => $users]); } }The get method returns an Illuminate\Support\Collection instance containing the results of the query where each result is an instance of the PHP stdClass object. You may access each column's value by accessing the column as a property of the object:use Illuminate\Support\Facades\DB; $users = DB::table('users')->get(); foreach ($users as $user) { echo $user->name; }Laravel collections provide a variety of extremely powerful methods for mapping and reducing data. For more information on Laravel collections, check out the collection documentation.Retrieving A Single Row / Column From A TableIf you just need to retrieve a single row from a database table, you may use the DB facade's first method. This method will return a single stdClass object:$user=DB::table('users')->where('name', 'John')->first(); return $user->email;If you don't need an entire row, you may extract a single value from a record using the value method. This method will return the value of the column directly:$email=DB::table('users')->where('name', 'John')->value('email');To retrieve a single row by its id column value, use the find method:$user=DB::table('users')->find(3);Retrieving A List Of Column ValuesIf you would like to retrieve an Illuminate\Support\Collection instance containing the values of a single column, you may use the pluck method. In this example, we'll retrieve a collection of user titles:use Illuminate\Support\Facades\DB; $titles = DB::table('users')->pluck('title'); foreach ($titles as $title) { echo $title; }You may specify the column that the resulting collection should use as its keys by providing a second argument to the pluck method:$titles = DB::table('users')->pluck('title', 'name'); foreach ($titles as $name => $title) { echo $title; }Chunking ResultsIf you need to work with thousands of database records, consider using the chunk method provided by the DB facade. This method retrieves a small chunk of results at a time and feeds each chunk into a closure for processing. For example, let's retrieve the entire users table in chunks of 100 records at a time:use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->chunk(100, function ($users) { foreach ($users as $user) { // } });You may stop further chunks from being processed by returning false from the closure:DB::table('users')->orderBy('id')->chunk(100, function ($users) { // Process the records... return false; });If you are updating database records while chunking results, your chunk results could change in unexpected ways. If you plan to update the retrieved records while chunking, it is always best to use the chunkById method instead. This method will automatically paginate the results based on the record's primary key:DB::table('users')->where('active', false) ->chunkById(100, function ($users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } });When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results.Streaming Results LazilyThe lazy method works similarly to the chunk method in the sense that it executes the query in chunks. However, instead of passing each chunk into a callback, the lazy() method returns a LazyCollection, which lets you interact with the results as a single stream:use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->lazy()->each(function($user) { // });Once again, if you plan to update the retrieved records while iterating over them, it is best to use the lazyById or lazyByIdDesc methods instead. These methods will automatically paginate the results based on the record's primary key:DB::table('users')->where('active', false) ->lazyById()->each(function ($user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); });When updating or deleting records while iterating over them, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the results.AggregatesThe query builder also provides a variety of methods for retrieving aggregate values like count, max, min, avg, and sum. You may call any of these methods after constructing your query:use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); $price = DB::table('orders')->max('price');Of course, you may combine these methods with other clauses to fine-tune how your aggregate value is calculated:$price=DB::table('orders')->where('finalized', 1)->avg('price');Determining If Records ExistInstead of using the count method to determine if any records exist that match your query's constraints, you may use the exists and doesntExist methods:if (DB::table('orders')->where('finalized', 1)->exists()) { // ... } if (DB::table('orders')->where('finalized', 1)->doesntExist()) { // ... }Select StatementsSpecifying A Select ClauseYou may not always want to select all columns from a database table. Using the select method, you can specify a custom "select" clause for the query:use Illuminate\Support\Facades\DB; $users = DB::table('users') ->select('name', 'email as user_email') ->get();The distinct method allows you to force the query to return distinct results:$users=DB::table('users')->distinct()->get();If you already have a query builder instance and you wish to add a column to its existing select clause, you may use the addSelect method:$query=DB::table('users')->select('name'); $users=$query->addSelect('age')->get();Raw ExpressionsSometimes you may need to insert an arbitrary string into a query. To create a raw string expression, you may use the raw method provided by the DB facade:$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();Raw statements will be injected into the query as strings, so you should be extremely careful to avoid creating SQL injection vulnerabilities.Raw MethodsInstead of using the DB::raw method, you may also use the following methods to insert a raw expression into various parts of your query. Remember, Laravel can not guarantee that any query using raw expressions is protected against SQL injection vulnerabilities.selectRawThe selectRaw method can be used in place of addSelect(DB::raw(...)). This method accepts an optional array of bindings as its second argument:$orders=DB::table('orders')->selectRaw('price * ? as price_with_tax', [1.0825])->get();whereRaw / orWhereRawThe whereRaw and orWhereRaw methods can be used to inject a raw "where" clause into your query. These methods accept an optional array of bindings as their second argument:$orders=DB::table('orders')->whereRaw('price > IF(state = "TX", ?, 100)', [200])->get();havingRaw / orHavingRawThe havingRaw and orHavingRaw methods may be used to provide a raw string as the value of the "having" clause. These methods accept an optional array of bindings as their second argument:$orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get();orderByRawThe orderByRaw method may be used to provide a raw string as the value of the "order by" clause:$orders = DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get();groupByRawThe groupByRaw method may be used to provide a raw string as the value of the group by clause:$orders=DB::table('orders')->select('city', 'state')->groupByRaw('city, state')->get();JoinsInner Join ClauseThe query builder may also be used to add join clauses to your queries. To perform a basic "inner join", you may use the join method on a query builder instance. The first argument passed to the join method is the name of the table you need to join to, while the remaining arguments specify the column constraints for the join. You may even join multiple tables in a single query:use Illuminate\Support\Facades\DB; $users=DB::table('users')->join('contacts', 'users.id', '=', 'contacts.user_id')->join('orders', 'users.id', '=', 'orders.user_id')->select('users.*', 'contacts.phone', 'orders.price')->get();Left Join / Right Join ClauseIf you would like to perform a "left join" or "right join" instead of an "inner join", use the leftJoin or rightJoin methods. These methods have the same signature as the join method:$users=DB::table('users')->leftJoin('posts', 'users.id', '=', 'posts.user_id')->get(); $users=DB::table('users')->rightJoin('posts', 'users.id', '=', 'posts.user_id')->get();Cross Join ClauseYou may use the crossJoin method to perform a "cross join". Cross joins generate a cartesian product between the first table and the joined table:$sizes=DB::table('sizes')->crossJoin('colors')->get();Advanced Join ClausesYou may also specify more advanced join clauses. To get started, pass a closure as the second argument to the join method. The closure will receive a Illuminate\Database\Query\JoinClause instance which allows you to specify constraints on the "join" clause:DB::table('users')->join('contacts', function($join) {$join->on('users.id', '=', 'contacts.user_id')->orOn(...); })->get();If you would like to use a "where" clause on your joins, you may use the where and orWhere methods provided by the JoinClause instance. Instead of comparing two columns, these methods will compare the column against a value:DB::table('users')->join('contacts', function($join) {$join->on('users.id', '=', 'contacts.user_id')->where('contacts.user_id', '>', 5); })->get();Subquery JoinsYou may use the joinSub, leftJoinSub, and rightJoinSub methods to join a query to a subquery. Each of these methods receives three arguments: the subquery, its table alias, and a closure that defines the related columns. In this example, we will retrieve a collection of users where each user record also contains the created_at timestamp of the user's most recently published blog post:$latestPosts=DB::table('posts')->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))->where('is_published', true)->groupBy('user_id'); $users=DB::table('users')->joinSub($latestPosts, 'latest_posts', function($join) {$join->on('users.id', '=', 'latest_posts.user_id'); })->get();UnionsThe query builder also provides a convenient method to "union" two or more queries together. For example, you may create an initial query and use the union method to union it with more queries:use Illuminate\Support\Facades\DB; $first=DB::table('users')->whereNull('first_name'); $users=DB::table('users')->whereNull('last_name')->union($first)->get();In addition to the union method, the query builder provides a unionAll method. Queries that are combined using the unionAll method will not have their duplicate results removed. The unionAll method has the same method signature as the union method.Basic Where ClausesWhere ClausesYou may use the query builder's where method to add "where" clauses to the query. The most basic call to the where method requires three arguments. The first argument is the name of the column. The second argument is an operator, which can be any of the database's supported operators. The third argument is the value to compare against the column's value.For example, the following query retrieves users where the value of the votes column is equal to 100 and the value of the age column is greater than 35:$users=DB::table('users')->where('votes', '=', 100)->where('age', '>', 35)->get();For convenience, if you want to verify that a column is = to a given value, you may pass the value as the second argument to the where method. Laravel will assume you would like to use the = operator:$users=DB::table('users')->where('votes', 100)->get();As previously mentioned, you may use any operator that is supported by your database system:$users=DB::table('users')->where('votes', '>=', 100)->get(); $users=DB::table('users')->where('votes', '<>', 100)->get(); $users=DB::table('users')->where('name', 'like', 'T%')->get();You may also pass an array of conditions to the where function. Each element of the array should be an array containing the three arguments typically passed to the where method:$users=DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'],])->get();PDO does not support binding column names. Therefore, you should never allow user input to dictate the column names referenced by your queries, including "order by" columns.Or Where ClausesWhen chaining together calls to the query builder's where method, the "where" clauses will be joined together using the and operator. However, you may use the orWhere method to join a clause to the query using the or operator. The orWhere method accepts the same arguments as the where method:$users=DB::table('users')->where('votes', '>', 100)->orWhere('name', 'John')->get();If you need to group an "or" condition within parentheses, you may pass a closure as the first argument to the orWhere method:$users=DB::table('users')->where('votes', '>', 100)->orWhere(function($query) {$query->where('name', 'Abigail')->where('votes', '>', 50); })->get();The example above will produce the following SQL:select*from users where votes >100or (name='Abigail'and votes >50)You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.JSON Where ClausesLaravel also supports querying JSON column types on databases that provide support for JSON column types. Currently, this includes MySQL 5.7+, PostgreSQL, SQL Server 2016, and SQLite 3.9.0 (with the JSON1 extension). To query a JSON column, use the -> operator:$users=DB::table('users')->where('preferences->dining->meal', 'salad')->get();You may use whereJsonContains to query JSON arrays. This feature is not supported by the SQLite database:$users=DB::table('users')->whereJsonContains('options->languages', 'en')->get();If your application uses the MySQL or PostgreSQL databases, you may pass an array of values to the whereJsonContains method:$users=DB::table('users')->whereJsonContains('options->languages', ['en', 'de'])->get();You may use whereJsonLength method to query JSON arrays by their length:$users=DB::table('users')->whereJsonLength('options->languages', 0)->get(); $users=DB::table('users')->whereJsonLength('options->languages', '>', 1)->get();Additional Where ClauseswhereBetween / orWhereBetweenThe whereBetween method verifies that a column's value is between two values:$users=DB::table('users')->whereBetween('votes', [1, 100])->get();whereNotBetween / orWhereNotBetweenThe whereNotBetween method verifies that a column's value lies outside of two values:$users=DB::table('users')->whereNotBetween('votes', [1, 100])->get();whereIn / whereNotIn / orWhereIn / orWhereNotInThe whereIn method verifies that a given column's value is contained within the given array:$users=DB::table('users')->whereIn('id', [1, 2, 3])->get();The whereNotIn method verifies that the given column's value is not contained in the given array:$users=DB::table('users')->whereNotIn('id', [1, 2, 3])->get();If you are adding a large array of integer bindings to your query, the whereIntegerInRaw or whereIntegerNotInRaw methods may be used to greatly reduce your memory usage.whereNull / whereNotNull / orWhereNull / orWhereNotNullThe whereNull method verifies that the value of the given column is NULL:$users=DB::table('users')->whereNull('updated_at')->get();The whereNotNull method verifies that the column's value is not NULL:$users=DB::table('users')->whereNotNull('updated_at')->get();whereDate / whereMonth / whereDay / whereYear / whereTimeThe whereDate method may be used to compare a column's value against a date:$users=DB::table('users')->whereDate('created_at', '2016-12-31')->get();The whereMonth method may be used to compare a column's value against a specific month:$users=DB::table('users')->whereMonth('created_at', '12')->get();The whereDay method may be used to compare a column's value against a specific day of the month:$users=DB::table('users')->whereDay('created_at', '31')->get();The whereYear method may be used to compare a column's value against a specific year:$users=DB::table('users')->whereYear('created_at', '2016')->get();The whereTime method may be used to compare a column's value against a specific time:$users=DB::table('users')->whereTime('created_at', '=', '11:20:45')->get();whereColumn / orWhereColumnThe whereColumn method may be used to verify that two columns are equal:$users=DB::table('users')->whereColumn('first_name', 'last_name')->get();You may also pass a comparison operator to the whereColumn method:$users=DB::table('users')->whereColumn('updated_at', '>', 'created_at')->get();You may also pass an array of column comparisons to the whereColumn method. These conditions will be joined using the and operator:$users=DB::table('users')->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'], ])->get();Logical GroupingSometimes you may need to group several "where" clauses within parentheses in order to achieve your query's desired logical grouping. In fact, you should generally always group calls to the orWhere method in parentheses in order to avoid unexpected query behavior. To accomplish this, you may pass a closure to the where method:$users=DB::table('users')->where('name', '=', 'John')->where(function($query) {$query->where('votes', '>', 100)->orWhere('title', '=', 'Admin'); })->get();As you can see, passing a closure into the where method instructs the query builder to begin a constraint group. The closure will receive a query builder instance which you can use to set the constraints that should be contained within the parenthesis group. The example above will produce the following SQL:select*from users wherename='John'and (votes >100or title ='Admin')You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.Advanced Where ClausesWhere Exists ClausesThe whereExists method allows you to write "where exists" SQL clauses. The whereExists method accepts a closure which will receive a query builder instance, allowing you to define the query that should be placed inside of the "exists" clause:$users=DB::table('users')->whereExists(function($query) {$query->select(DB::raw(1))->from('orders')->whereColumn('orders.user_id', 'users.id'); })->get();The query above will produce the following SQL:select*from userswhereexists (select1from orderswhereorders.user_id=users.id)Subquery Where ClausesSometimes you may need to construct a "where" clause that compares the results of a subquery to a given value. You may accomplish this by passing a closure and a value to the where method. For example, the following query will retrieve all users who have a recent "membership" of a given type;use App\Models\User; $users=User::where(function($query) {$query->select('type')->from('membership')->whereColumn('membership.user_id', 'users.id')->orderByDesc('membership.start_date')->limit(1);}, 'Pro')->get();Or, you may need to construct a "where" clause that compares a column to the results of a subquery. You may accomplish this by passing a column, operator, and closure to the where method. For example, the following query will retrieve all income records where the amount is less than average;use App\Models\Income; $incomes=Income::where('amount', '<', function($query) {$query->selectRaw('avg(i.amount)')->from('incomes as i');})->get();Ordering, Grouping, Limit & OffsetOrderingThe orderBy MethodThe orderBy method allows you to sort the results of the query by a given column. The first argument accepted by the orderBy method should be the column you wish to sort by, while the second argument determines the direction of the sort and may be either asc or desc:$users = DB::table('users') ->orderBy('name', 'desc') ->get();To sort by multiple columns, you may simply invoke orderBy as many times as necessary:$users = DB::table('users') ->orderBy('name', 'desc') ->orderBy('email', 'asc') ->get();The latest&oldest MethodsThe latest and oldest methods allow you to easily order results by date. By default, the result will be ordered by the table's created_at column. Or, you may pass the column name that you wish to sort by:$user=DB::table('users')->latest()->first();Random OrderingThe inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:$randomUser=DB::table('users')->inRandomOrder()->first();Removing Existing OrderingsThe reorder method removes all of the "order by" clauses that have previously been applied to the query:$query = DB::table('users')->orderBy('name'); $unorderedUsers = $query->reorder()->get();You may pass a column and direction when calling the reorder method in order to remove all existing "order by" clauses and apply an entirely new order to the query:$query = DB::table('users')->orderBy('name'); $usersOrderedByEmail = $query->reorder('email', 'desc')->get();GroupingThe groupBy&having MethodsAs you might expect, the groupBy and having methods may be used to group the query results. The having method's signature is similar to that of the where method:$users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get();You can use the havingBetween method to filter the results within a given range:$report = DB::table('orders') ->selectRaw('count(id) as number_of_orders, customer_id') ->groupBy('customer_id') ->havingBetween('number_of_orders', [5, 15]) ->get();You may pass multiple arguments to the groupBy method to group by multiple columns:$users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get();To build more advanced having statements, see the havingRaw method.Limit & OffsetThe skip&take MethodsYou may use the skip and take methods to limit the number of results returned from the query or to skip a given number of results in the query:$users = DB::table('users')->skip(10)->take(5)->get();Alternatively, you may use the limit and offset methods. These methods are functionally equivalent to the take and skip methods, respectively:$users = DB::table('users') ->offset(10) ->limit(5) ->get();Conditional ClausesSometimes you may want certain query clauses to apply to a query based on another condition. For instance, you may only want to apply a where statement if a given input value is present on the incoming HTTP request. You may accomplish this using the when method:$role = $request->input('role'); $users = DB::table('users') ->when($role, function ($query, $role) { return $query->where('role_id', $role); }) ->get();The when method only executes the given closure when the first argument is true. If the first argument is false, the closure will not be executed. So, in the example above, the closure given to the when method will only be invoked if the role field is present on the incoming request and evaluates to true.You may pass another closure as the third argument to the when method. This closure will only execute if the first argument evaluates as false. To illustrate how this feature may be used, we will use it to configure the default ordering of a query:$sortByVotes = $request->input('sort_by_votes'); $users = DB::table('users') ->when($sortByVotes, function ($query, $sortByVotes) { return $query->orderBy('votes'); }, function ($query) { return $query->orderBy('name'); }) ->get();Insert StatementsThe query builder also provides an insert method that may be used to insert records into the database table. The insert method accepts an array of column names and values:DB::table('users')->insert([ 'email' => 'kayla@example.com', 'votes' => 0 ]);You may insert several records at once by passing an array of arrays. Each array represents a record that should be inserted into the table:DB::table('users')->insert([ ['email' => 'picard@example.com', 'votes' => 0], ['email' => 'janeway@example.com', 'votes' => 0], ]);The insertOrIgnore method will ignore errors while inserting records into the database:DB::table('users')->insertOrIgnore([ ['id' => 1, 'email' => 'sisko@example.com'], ['id' => 2, 'email' => 'archer@example.com'], ]);insertOrIgnore will ignore duplicate records and also may ignore other types of errors depending on the database engine. For example, insertOrIgnore will bypass MySQL's strict mode.Auto-Incrementing IDsIf the table has an auto-incrementing id, use the insertGetId method to insert a record and then retrieve the ID:$id = DB::table('users')->insertGetId( ['email' => 'john@example.com', 'votes' => 0] );When using PostgreSQL the insertGetId method expects the auto-incrementing column to be named id. If you would like to retrieve the ID from a different "sequence", you may pass the column name as the second parameter to the insertGetId method.UpsertsThe upsert method will insert records that do not exist and update the records that already exist with new values that you may specify. 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 columns that should be updated if a matching record already exists in the database:DB::table('flights')->upsert([ ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150] ], ['departure', 'destination'], ['price']);In the example above, Laravel will attempt to insert two records. If a record already exists with the same departure and destination column values, Laravel will update that record's price column.All databases except SQL Server require the columns in the second argument of the upsert method to have a "primary" or "unique" index. In addition, the MySQL database driver ignores the second argument of the upsert method and always uses the "primary" and "unique" indexes of the table to detect existing records.Update StatementsIn addition to inserting records into the database, the query builder can also update existing records using the update method. The update method, like the insert method, accepts an array of column and value pairs indicating the columns to be updated. The update method returns the number of affected rows. You may constrain the update query using where clauses:$affected = DB::table('users') ->where('id', 1) ->update(['votes' => 1]);Update Or InsertSometimes you may want to update an existing record in the database or create it if no matching record exists. In this scenario, the updateOrInsert method may be used. The updateOrInsert method accepts two arguments: an array of conditions by which to find the record, and an array of column and value pairs indicating the columns to be updated.The updateOrInsert method will attempt to locate a matching database record using the first argument's column and value pairs. If the record exists, it will be updated with the values in the second argument. If the record can not be found, a new record will be inserted with the merged attributes of both arguments:DB::table('users') ->updateOrInsert( ['email' => 'john@example.com', 'name' => 'John'], ['votes' => '2'] );Updating JSON ColumnsWhen updating a JSON column, you should use -> syntax to update the appropriate key in the JSON object. This operation is supported on MySQL 5.7+ and PostgreSQL 9.5+:$affected = DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]);Increment & DecrementThe query builder also provides convenient methods for incrementing or decrementing the value of a given column. Both of these methods accept at least one argument: the column to modify. A second argument may be provided to specify the amount by which the column should be incremented or decremented:DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5);You may also specify additional columns to update during the operation:DB::table('users')->increment('votes', 1, ['name' => 'John']);Delete StatementsThe query builder's delete method may be used to delete records from the table. The delete method returns the number of affected rows. You may constrain delete statements by adding "where" clauses before calling the delete method:$deleted = DB::table('users')->delete(); $deleted = DB::table('users')->where('votes', '>', 100)->delete();If you wish to truncate an entire table, which will remove all records from the table and reset the auto-incrementing ID to zero, you may use the truncate method:DB::table('users')->truncate();Table Truncation & PostgreSQLWhen truncating a PostgreSQL database, the CASCADE behavior will be applied. This means that all foreign key related records in other tables will be deleted as well.Pessimistic LockingThe query builder also includes a few functions to help you achieve "pessimistic locking" when executing your select statements. To execute a statement with a "shared lock", you may call the sharedLock method. A shared lock prevents the selected rows from being modified until your transaction is committed:DB::table('users')->where('votes', '>', 100)->sharedLock()->get();Alternatively, you may use the lockForUpdate method. A "for update" lock prevents the selected records from being modified or from being selected with another shared lock:DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();DebuggingYou may use the dd and dump methods while building a query to dump the current query bindings and SQL. The dd method will display the debug information and then stop executing the request. The dump method will display the debug information but allow the request to continue executing:DB::table('users')->where('votes', '>', 100)->dd(); DB::table('users')->where('votes', '>', 100)->dump();IntroductionLaravel's database query builder provides a convenient, fluent interface to creating and running database queries. It can be used to perform most database operations in your application and works perfectly with all of Laravel's supported database systems.The Laravel query builder uses PDO parameter binding to protect your application against SQL injection attacks. There is no need to clean or sanitize strings passed to the query builder as query bindings.PDO does not support binding column names. Therefore, you should never allow user input to dictate the column names referenced by your queries, including "order by" columns.Running Database QueriesRetrieving All Rows From A TableYou may use the table method provided by the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally retrieve the results of the query using the get method:<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\DB; class UserController extends Controller { /** * Show a list of all of the application's users. * * @return \Illuminate\Http\Response */ public function index() { $users = DB::table('users')->get(); return view('user.index', ['users' => $users]); } }The get method returns an Illuminate\Support\Collection instance containing the results of the query where each result is an instance of the PHP stdClass object. You may access each column's value by accessing the column as a property of the object:use Illuminate\Support\Facades\DB; $users = DB::table('users')->get(); foreach ($users as $user) { echo $user->name; }Laravel collections provide a variety of extremely powerful methods for mapping and reducing data. For more information on Laravel collections, check out the collection documentation.Retrieving A Single Row / Column From A TableIf you just need to retrieve a single row from a database table, you may use the DB facade's first method. This method will return a single stdClass object:$user=DB::table('users')->where('name', 'John')->first(); return $user->email;If you don't need an entire row, you may extract a single value from a record using the value method. This method will return the value of the column directly:$email=DB::table('users')->where('name', 'John')->value('email');To retrieve a single row by its id column value, use the find method:$user=DB::table('users')->find(3);Retrieving A List Of Column ValuesIf you would like to retrieve an Illuminate\Support\Collection instance containing the values of a single column, you may use the pluck method. In this example, we'll retrieve a collection of user titles:use Illuminate\Support\Facades\DB; $titles = DB::table('users')->pluck('title'); foreach ($titles as $title) { echo $title; }You may specify the column that the resulting collection should use as its keys by providing a second argument to the pluck method:$titles = DB::table('users')->pluck('title', 'name'); foreach ($titles as $name => $title) { echo $title; }Chunking ResultsIf you need to work with thousands of database records, consider using the chunk method provided by the DB facade. This method retrieves a small chunk of results at a time and feeds each chunk into a closure for processing. For example, let's retrieve the entire users table in chunks of 100 records at a time:use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->chunk(100, function ($users) { foreach ($users as $user) { // } });You may stop further chunks from being processed by returning false from the closure:DB::table('users')->orderBy('id')->chunk(100, function ($users) { // Process the records... return false; });If you are updating database records while chunking results, your chunk results could change in unexpected ways. If you plan to update the retrieved records while chunking, it is always best to use the chunkById method instead. This method will automatically paginate the results based on the record's primary key:DB::table('users')->where('active', false) ->chunkById(100, function ($users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } });When updating or deleting records inside the chunk callback, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the chunked results.Streaming Results LazilyThe lazy method works similarly to the chunk method in the sense that it executes the query in chunks. However, instead of passing each chunk into a callback, the lazy() method returns a LazyCollection, which lets you interact with the results as a single stream:use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->lazy()->each(function($user) { // });Once again, if you plan to update the retrieved records while iterating over them, it is best to use the lazyById or lazyByIdDesc methods instead. These methods will automatically paginate the results based on the record's primary key:DB::table('users')->where('active', false) ->lazyById()->each(function ($user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); });When updating or deleting records while iterating over them, any changes to the primary key or foreign keys could affect the chunk query. This could potentially result in records not being included in the results.AggregatesThe query builder also provides a variety of methods for retrieving aggregate values like count, max, min, avg, and sum. You may call any of these methods after constructing your query:use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); $price = DB::table('orders')->max('price');Of course, you may combine these methods with other clauses to fine-tune how your aggregate value is calculated:$price=DB::table('orders')->where('finalized', 1)->avg('price');Determining If Records ExistInstead of using the count method to determine if any records exist that match your query's constraints, you may use the exists and doesntExist methods:if (DB::table('orders')->where('finalized', 1)->exists()) { // ... } if (DB::table('orders')->where('finalized', 1)->doesntExist()) { // ... }Select StatementsSpecifying A Select ClauseYou may not always want to select all columns from a database table. Using the select method, you can specify a custom "select" clause for the query:use Illuminate\Support\Facades\DB; $users = DB::table('users') ->select('name', 'email as user_email') ->get();The distinct method allows you to force the query to return distinct results:$users=DB::table('users')->distinct()->get();If you already have a query builder instance and you wish to add a column to its existing select clause, you may use the addSelect method:$query=DB::table('users')->select('name'); $users=$query->addSelect('age')->get();Raw ExpressionsSometimes you may need to insert an arbitrary string into a query. To create a raw string expression, you may use the raw method provided by the DB facade:$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();Raw statements will be injected into the query as strings, so you should be extremely careful to avoid creating SQL injection vulnerabilities.Raw MethodsInstead of using the DB::raw method, you may also use the following methods to insert a raw expression into various parts of your query. Remember, Laravel can not guarantee that any query using raw expressions is protected against SQL injection vulnerabilities.selectRawThe selectRaw method can be used in place of addSelect(DB::raw(...)). This method accepts an optional array of bindings as its second argument:$orders=DB::table('orders')->selectRaw('price * ? as price_with_tax', [1.0825])->get();whereRaw / orWhereRawThe whereRaw and orWhereRaw methods can be used to inject a raw "where" clause into your query. These methods accept an optional array of bindings as their second argument:$orders=DB::table('orders')->whereRaw('price > IF(state = "TX", ?, 100)', [200])->get();havingRaw / orHavingRawThe havingRaw and orHavingRaw methods may be used to provide a raw string as the value of the "having" clause. These methods accept an optional array of bindings as their second argument:$orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get();orderByRawThe orderByRaw method may be used to provide a raw string as the value of the "order by" clause:$orders = DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get();groupByRawThe groupByRaw method may be used to provide a raw string as the value of the group by clause:$orders=DB::table('orders')->select('city', 'state')->groupByRaw('city, state')->get();JoinsInner Join ClauseThe query builder may also be used to add join clauses to your queries. To perform a basic "inner join", you may use the join method on a query builder instance. The first argument passed to the join method is the name of the table you need to join to, while the remaining arguments specify the column constraints for the join. You may even join multiple tables in a single query:use Illuminate\Support\Facades\DB; $users=DB::table('users')->join('contacts', 'users.id', '=', 'contacts.user_id')->join('orders', 'users.id', '=', 'orders.user_id')->select('users.*', 'contacts.phone', 'orders.price')->get();Left Join / Right Join ClauseIf you would like to perform a "left join" or "right join" instead of an "inner join", use the leftJoin or rightJoin methods. These methods have the same signature as the join method:$users=DB::table('users')->leftJoin('posts', 'users.id', '=', 'posts.user_id')->get(); $users=DB::table('users')->rightJoin('posts', 'users.id', '=', 'posts.user_id')->get();Cross Join ClauseYou may use the crossJoin method to perform a "cross join". Cross joins generate a cartesian product between the first table and the joined table:$sizes=DB::table('sizes')->crossJoin('colors')->get();Advanced Join ClausesYou may also specify more advanced join clauses. To get started, pass a closure as the second argument to the join method. The closure will receive a Illuminate\Database\Query\JoinClause instance which allows you to specify constraints on the "join" clause:DB::table('users')->join('contacts', function($join) {$join->on('users.id', '=', 'contacts.user_id')->orOn(...); })->get();If you would like to use a "where" clause on your joins, you may use the where and orWhere methods provided by the JoinClause instance. Instead of comparing two columns, these methods will compare the column against a value:DB::table('users')->join('contacts', function($join) {$join->on('users.id', '=', 'contacts.user_id')->where('contacts.user_id', '>', 5); })->get();Subquery JoinsYou may use the joinSub, leftJoinSub, and rightJoinSub methods to join a query to a subquery. Each of these methods receives three arguments: the subquery, its table alias, and a closure that defines the related columns. In this example, we will retrieve a collection of users where each user record also contains the created_at timestamp of the user's most recently published blog post:$latestPosts=DB::table('posts')->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))->where('is_published', true)->groupBy('user_id'); $users=DB::table('users')->joinSub($latestPosts, 'latest_posts', function($join) {$join->on('users.id', '=', 'latest_posts.user_id'); })->get();UnionsThe query builder also provides a convenient method to "union" two or more queries together. For example, you may create an initial query and use the union method to union it with more queries:use Illuminate\Support\Facades\DB; $first=DB::table('users')->whereNull('first_name'); $users=DB::table('users')->whereNull('last_name')->union($first)->get();In addition to the union method, the query builder provides a unionAll method. Queries that are combined using the unionAll method will not have their duplicate results removed. The unionAll method has the same method signature as the union method.Basic Where ClausesWhere ClausesYou may use the query builder's where method to add "where" clauses to the query. The most basic call to the where method requires three arguments. The first argument is the name of the column. The second argument is an operator, which can be any of the database's supported operators. The third argument is the value to compare against the column's value.For example, the following query retrieves users where the value of the votes column is equal to 100 and the value of the age column is greater than 35:$users=DB::table('users')->where('votes', '=', 100)->where('age', '>', 35)->get();For convenience, if you want to verify that a column is = to a given value, you may pass the value as the second argument to the where method. Laravel will assume you would like to use the = operator:$users=DB::table('users')->where('votes', 100)->get();As previously mentioned, you may use any operator that is supported by your database system:$users=DB::table('users')->where('votes', '>=', 100)->get(); $users=DB::table('users')->where('votes', '<>', 100)->get(); $users=DB::table('users')->where('name', 'like', 'T%')->get();You may also pass an array of conditions to the where function. Each element of the array should be an array containing the three arguments typically passed to the where method:$users=DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'],])->get();PDO does not support binding column names. Therefore, you should never allow user input to dictate the column names referenced by your queries, including "order by" columns.Or Where ClausesWhen chaining together calls to the query builder's where method, the "where" clauses will be joined together using the and operator. However, you may use the orWhere method to join a clause to the query using the or operator. The orWhere method accepts the same arguments as the where method:$users=DB::table('users')->where('votes', '>', 100)->orWhere('name', 'John')->get();If you need to group an "or" condition within parentheses, you may pass a closure as the first argument to the orWhere method:$users=DB::table('users')->where('votes', '>', 100)->orWhere(function($query) {$query->where('name', 'Abigail')->where('votes', '>', 50); })->get();The example above will produce the following SQL:select*from users where votes >100or (name='Abigail'and votes >50)You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.JSON Where ClausesLaravel also supports querying JSON column types on databases that provide support for JSON column types. Currently, this includes MySQL 5.7+, PostgreSQL, SQL Server 2016, and SQLite 3.9.0 (with the JSON1 extension). To query a JSON column, use the -> operator:$users=DB::table('users')->where('preferences->dining->meal', 'salad')->get();You may use whereJsonContains to query JSON arrays. This feature is not supported by the SQLite database:$users=DB::table('users')->whereJsonContains('options->languages', 'en')->get();If your application uses the MySQL or PostgreSQL databases, you may pass an array of values to the whereJsonContains method:$users=DB::table('users')->whereJsonContains('options->languages', ['en', 'de'])->get();You may use whereJsonLength method to query JSON arrays by their length:$users=DB::table('users')->whereJsonLength('options->languages', 0)->get(); $users=DB::table('users')->whereJsonLength('options->languages', '>', 1)->get();Additional Where ClauseswhereBetween / orWhereBetweenThe whereBetween method verifies that a column's value is between two values:$users=DB::table('users')->whereBetween('votes', [1, 100])->get();whereNotBetween / orWhereNotBetweenThe whereNotBetween method verifies that a column's value lies outside of two values:$users=DB::table('users')->whereNotBetween('votes', [1, 100])->get();whereIn / whereNotIn / orWhereIn / orWhereNotInThe whereIn method verifies that a given column's value is contained within the given array:$users=DB::table('users')->whereIn('id', [1, 2, 3])->get();The whereNotIn method verifies that the given column's value is not contained in the given array:$users=DB::table('users')->whereNotIn('id', [1, 2, 3])->get();If you are adding a large array of integer bindings to your query, the whereIntegerInRaw or whereIntegerNotInRaw methods may be used to greatly reduce your memory usage.whereNull / whereNotNull / orWhereNull / orWhereNotNullThe whereNull method verifies that the value of the given column is NULL:$users=DB::table('users')->whereNull('updated_at')->get();The whereNotNull method verifies that the column's value is not NULL:$users=DB::table('users')->whereNotNull('updated_at')->get();whereDate / whereMonth / whereDay / whereYear / whereTimeThe whereDate method may be used to compare a column's value against a date:$users=DB::table('users')->whereDate('created_at', '2016-12-31')->get();The whereMonth method may be used to compare a column's value against a specific month:$users=DB::table('users')->whereMonth('created_at', '12')->get();The whereDay method may be used to compare a column's value against a specific day of the month:$users=DB::table('users')->whereDay('created_at', '31')->get();The whereYear method may be used to compare a column's value against a specific year:$users=DB::table('users')->whereYear('created_at', '2016')->get();The whereTime method may be used to compare a column's value against a specific time:$users=DB::table('users')->whereTime('created_at', '=', '11:20:45')->get();whereColumn / orWhereColumnThe whereColumn method may be used to verify that two columns are equal:$users=DB::table('users')->whereColumn('first_name', 'last_name')->get();You may also pass a comparison operator to the whereColumn method:$users=DB::table('users')->whereColumn('updated_at', '>', 'created_at')->get();You may also pass an array of column comparisons to the whereColumn method. These conditions will be joined using the and operator:$users=DB::table('users')->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'], ])->get();Logical GroupingSometimes you may need to group several "where" clauses within parentheses in order to achieve your query's desired logical grouping. In fact, you should generally always group calls to the orWhere method in parentheses in order to avoid unexpected query behavior. To accomplish this, you may pass a closure to the where method:$users=DB::table('users')->where('name', '=', 'John')->where(function($query) {$query->where('votes', '>', 100)->orWhere('title', '=', 'Admin'); })->get();As you can see, passing a closure into the where method instructs the query builder to begin a constraint group. The closure will receive a query builder instance which you can use to set the constraints that should be contained within the parenthesis group. The example above will produce the following SQL:select*from users wherename='John'and (votes >100or title ='Admin')You should always group orWhere calls in order to avoid unexpected behavior when global scopes are applied.Advanced Where ClausesWhere Exists ClausesThe whereExists method allows you to write "where exists" SQL clauses. The whereExists method accepts a closure which will receive a query builder instance, allowing you to define the query that should be placed inside of the "exists" clause:$users=DB::table('users')->whereExists(function($query) {$query->select(DB::raw(1))->from('orders')->whereColumn('orders.user_id', 'users.id'); })->get();The query above will produce the following SQL:select*from userswhereexists (select1from orderswhereorders.user_id=users.id)Subquery Where ClausesSometimes you may need to construct a "where" clause that compares the results of a subquery to a given value. You may accomplish this by passing a closure and a value to the where method. For example, the following query will retrieve all users who have a recent "membership" of a given type;use App\Models\User; $users=User::where(function($query) {$query->select('type')->from('membership')->whereColumn('membership.user_id', 'users.id')->orderByDesc('membership.start_date')->limit(1);}, 'Pro')->get();Or, you may need to construct a "where" clause that compares a column to the results of a subquery. You may accomplish this by passing a column, operator, and closure to the where method. For example, the following query will retrieve all income records where the amount is less than average;use App\Models\Income; $incomes=Income::where('amount', '<', function($query) {$query->selectRaw('avg(i.amount)')->from('incomes as i');})->get();Ordering, Grouping, Limit & OffsetOrderingThe orderBy MethodThe orderBy method allows you to sort the results of the query by a given column. The first argument accepted by the orderBy method should be the column you wish to sort by, while the second argument determines the direction of the sort and may be either asc or desc:$users = DB::table('users') ->orderBy('name', 'desc') ->get();To sort by multiple columns, you may simply invoke orderBy as many times as necessary:$users = DB::table('users') ->orderBy('name', 'desc') ->orderBy('email', 'asc') ->get();The latest&oldest MethodsThe latest and oldest methods allow you to easily order results by date. By default, the result will be ordered by the table's created_at column. Or, you may pass the column name that you wish to sort by:$user=DB::table('users')->latest()->first();Random OrderingThe inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:$randomUser=DB::table('users')->inRandomOrder()->first();Removing Existing OrderingsThe reorder method removes all of the "order by" clauses that have previously been applied to the query:$query = DB::table('users')->orderBy('name'); $unorderedUsers = $query->reorder()->get();You may pass a column and direction when calling the reorder method in order to remove all existing "order by" clauses and apply an entirely new order to the query:$query = DB::table('users')->orderBy('name'); $usersOrderedByEmail = $query->reorder('email', 'desc')->get();GroupingThe groupBy&having MethodsAs you might expect, the groupBy and having methods may be used to group the query results. The having method's signature is similar to that of the where method:$users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get();You can use the havingBetween method to filter the results within a given range:$report = DB::table('orders') ->selectRaw('count(id) as number_of_orders, customer_id') ->groupBy('customer_id') ->havingBetween('number_of_orders', [5, 15]) ->get();You may pass multiple arguments to the groupBy method to group by multiple columns:$users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get();To build more advanced having statements, see the havingRaw method.Limit & OffsetThe skip&take MethodsYou may use the skip and take methods to limit the number of results returned from the query or to skip a given number of results in the query:$users = DB::table('users')->skip(10)->take(5)->get();Alternatively, you may use the limit and offset methods. These methods are functionally equivalent to the take and skip methods, respectively:$users = DB::table('users') ->offset(10) ->limit(5) ->get();Conditional ClausesSometimes you may want certain query clauses to apply to a query based on another condition. For instance, you may only want to apply a where statement if a given input value is present on the incoming HTTP request. You may accomplish this using the when method:$role = $request->input('role'); $users = DB::table('users') ->when($role, function ($query, $role) { return $query->where('role_id', $role); }) ->get();The when method only executes the given closure when the first argument is true. If the first argument is false, the closure will not be executed. So, in the example above, the closure given to the when method will only be invoked if the role field is present on the incoming request and evaluates to true.You may pass another closure as the third argument to the when method. This closure will only execute if the first argument evaluates as false. To illustrate how this feature may be used, we will use it to configure the default ordering of a query:$sortByVotes = $request->input('sort_by_votes'); $users = DB::table('users') ->when($sortByVotes, function ($query, $sortByVotes) { return $query->orderBy('votes'); }, function ($query) { return $query->orderBy('name'); }) ->get();Insert StatementsThe query builder also provides an insert method that may be used to insert records into the database table. The insert method accepts an array of column names and values:DB::table('users')->insert([ 'email' => 'kayla@example.com', 'votes' => 0 ]);You may insert several records at once by passing an array of arrays. Each array represents a record that should be inserted into the table:DB::table('users')->insert([ ['email' => 'picard@example.com', 'votes' => 0], ['email' => 'janeway@example.com', 'votes' => 0], ]);The insertOrIgnore method will ignore errors while inserting records into the database:DB::table('users')->insertOrIgnore([ ['id' => 1, 'email' => 'sisko@example.com'], ['id' => 2, 'email' => 'archer@example.com'], ]);insertOrIgnore will ignore duplicate records and also may ignore other types of errors depending on the database engine. For example, insertOrIgnore will bypass MySQL's strict mode.Auto-Incrementing IDsIf the table has an auto-incrementing id, use the insertGetId method to insert a record and then retrieve the ID:$id = DB::table('users')->insertGetId( ['email' => 'john@example.com', 'votes' => 0] );When using PostgreSQL the insertGetId method expects the auto-incrementing column to be named id. If you would like to retrieve the ID from a different "sequence", you may pass the column name as the second parameter to the insertGetId method.UpsertsThe upsert method will insert records that do not exist and update the records that already exist with new values that you may specify. 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 columns that should be updated if a matching record already exists in the database:DB::table('flights')->upsert([ ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150] ], ['departure', 'destination'], ['price']);In the example above, Laravel will attempt to insert two records. If a record already exists with the same departure and destination column values, Laravel will update that record's price column.All databases except SQL Server require the columns in the second argument of the upsert method to have a "primary" or "unique" index. In addition, the MySQL database driver ignores the second argument of the upsert method and always uses the "primary" and "unique" indexes of the table to detect existing records.Update StatementsIn addition to inserting records into the database, the query builder can also update existing records using the update method. The update method, like the insert method, accepts an array of column and value pairs indicating the columns to be updated. The update method returns the number of affected rows. You may constrain the update query using where clauses:$affected = DB::table('users') ->where('id', 1) ->update(['votes' => 1]);Update Or InsertSometimes you may want to update an existing record in the database or create it if no matching record exists. In this scenario, the updateOrInsert method may be used. The updateOrInsert method accepts two arguments: an array of conditions by which to find the record, and an array of column and value pairs indicating the columns to be updated.The updateOrInsert method will attempt to locate a matching database record using the first argument's column and value pairs. If the record exists, it will be updated with the values in the second argument. If the record can not be found, a new record will be inserted with the merged attributes of both arguments:DB::table('users') ->updateOrInsert( ['email' => 'john@example.com', 'name' => 'John'], ['votes' => '2'] );Updating JSON ColumnsWhen updating a JSON column, you should use -> syntax to update the appropriate key in the JSON object. This operation is supported on MySQL 5.7+ and PostgreSQL 9.5+:$affected = DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]);Increment & DecrementThe query builder also provides convenient methods for incrementing or decrementing the value of a given column. Both of these methods accept at least one argument: the column to modify. A second argument may be provided to specify the amount by which the column should be incremented or decremented:DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5);You may also specify additional columns to update during the operation:DB::table('users')->increment('votes', 1, ['name' => 'John']);Delete StatementsThe query builder's delete method may be used to delete records from the table. The delete method returns the number of affected rows. You may constrain delete statements by adding "where" clauses before calling the delete method:$deleted = DB::table('users')->delete(); $deleted = DB::table('users')->where('votes', '>', 100)->delete();If you wish to truncate an entire table, which will remove all records from the table and reset the auto-incrementing ID to zero, you may use the truncate method:DB::table('users')->truncate();Table Truncation & PostgreSQLWhen truncating a PostgreSQL database, the CASCADE behavior will be applied. This means that all foreign key related records in other tables will be deleted as well.Pessimistic LockingThe query builder also includes a few functions to help you achieve "pessimistic locking" when executing your select statements. To execute a statement with a "shared lock", you may call the sharedLock method. A shared lock prevents the selected rows from being modified until your transaction is committed:DB::table('users')->where('votes', '>', 100)->sharedLock()->get();Alternatively, you may use the lockForUpdate method. A "for update" lock prevents the selected records from being modified or from being selected with another shared lock:DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();DebuggingYou may use the dd and dump methods while building a query to dump the current query bindings and SQL. The dd method will display the debug information and then stop executing the request. The dump method will display the debug information but allow the request to continue executing:DB::table('users')->where('votes', '>', 100)->dd(); DB::table('users')->where('votes', '>', 100)->dump();
VSCode快捷键按Press功能FunctionCtrl+Shift+P,F1显示命令面板 Show Command PaletteCtrl + P快速打开 Quick OpenCtrl + Shift + N新窗口/实例 New window/instanceCtrl + Shift + W关闭窗口/实例 Close window/instance基础编辑Basic Editing按 Press功能 FunctionCtrl+X剪切行（空选定） Cut line (empty selection)Ctrl+C复制行（空选定）Copy line (empty selection)Alt+ ↑ / ↓向上/向下移动行 Move line up/downShift+Alt + ↓ / ↑向上/向下复制行 Copy line up/downCtrl+Shift+K删除行 Delete lineCtrl+Enter在下面插入行 Insert line belowCtrl+Shift+Enter在上面插入行 Insert line aboveCtrl+Shift+\跳到匹配的括号 Jump to matching bracketCtrl+] / [缩进/缩进行 Indent/outdent lineHome转到行首 Go to beginning of lineEnd转到行尾 Go to end of lineCtrl+Home转到文件开头 Go to beginning of fileCtrl+End转到文件末尾 Go to end of fileCtrl+↑ / ↓向上/向下滚动行 Scroll line up/downAlt+PgUp / PgDown向上/向下滚动页面 Scroll page up/downCtrl+Shift+[折叠（折叠）区域 Fold (collapse) regionCtrl+Shift+]展开（未折叠）区域 Unfold (uncollapse) regionCtrl+K Ctrl+[折叠（未折叠）所有子区域 Fold (collapse) all subregionsCtrl+K Ctrl+]展开（未折叠）所有子区域 Unfold (uncollapse) all subregionsCtrl+K Ctrl+0折叠（折叠）所有区域 Fold (collapse) all regionsCtrl+K Ctrl+J展开（未折叠）所有区域 Unfold (uncollapse) all regionsCtrl+K Ctrl+C添加行注释 Add line commentCtrl+K Ctrl+U删除行注释 Remove line commentCtrl+/切换行注释 Toggle line commentShift+Alt+A切换块注释 Toggle block commentAlt+Z切换换行 Toggle word wrap导航按 Press功能 FunctionCtrl + T显示所有符号 Show all SymbolsCtrl + G转到行... Go to Line...Ctrl + P转到文件... Go to File...Ctrl + Shift + O转到符号... Go to Symbol...Ctrl + Shift + M显示问题面板 Show Problems panelF8转到下一个错误或警告 Go to next error or warningShift + F8转到上一个错误或警告 Go to previous error or warningCtrl + Shift + Tab导航编辑器组历史记录 Navigate editor group historyAlt + ←/→返回/前进 Go back / forwardCtrl + M切换选项卡移动焦点 Toggle Tab moves focus搜索和替换 Search and replace按 Press功能 FunctionCtrl + F查找 FindCtrl + H替换 ReplaceF3 / Shift + F3查找下一个/上一个 Find next/previousAlt + Enter选择查找匹配的所有出现 Select all occurences of Find matchCtrl + D将选择添加到下一个查找匹配 Add selection to next Find matchCtrl + K Ctrl + D将最后一个选择移至下一个查找匹配项 Move last selection to next Find matchAlt + C / R / W切换区分大小写/正则表达式/整个词 Toggle case-sensitive / regex / whole word多光标和选择按 Press功能 FunctionAlt +单击插入光标 Insert cursorCtrl + Alt +↑/↓在上/下插入光标 Insert cursor above / belowCtrl + U撤消上一个光标操作 Undo last cursor operationShift + Alt + I在选定的每一行的末尾插入光标 Insert cursor at end of each line selectedCtrl + I选择当前行 Select current lineCtrl + Shift + L选择当前选择的所有出现 Select all occurrences of current selectionCtrl + F2选择当前字的所有出现 Select all occurrences of current wordShift + Alt + →展开选择 Expand selectionShift + Alt + ←缩小选择 Shrink selectionShift + Alt + （拖动鼠标）列（框）选择 Column (box) selectionCtrl + Shift + Alt +（箭头键）列（框）选择 Column (box) selectionCtrl + Shift + Alt + PgUp / PgDown列（框）选择页上/下 Column (box) selection page up/down丰富的语言编辑 Rich languages editing按 Press功能 FunctionCtrl + 空格触发建议 Trigger suggestionCtrl + Shift + Space触发器参数提示 Trigger parameter hintsTabEmmet 展开缩写 Emmet expand abbreviationShift + Alt + F格式化文档 Format documentCtrl + K Ctrl + F格式选定区域 Format selectionF12转到定义 Go to DefinitionAlt + F12Peek定义 Peek DefinitionCtrl + K F12打开定义到边 Open Definition to the sideCtrl + .快速解决 Quick FixShift + F12显示引用 Show ReferencesF2重命名符号 Rename SymbolCtrl + Shift + . /，替换为下一个/上一个值 Replace with next/previous valueCtrl + K Ctrl + X修剪尾随空格 Trim trailing whitespaceCtrl + K M更改文件语言 Change file language编辑器管理 Editor management按 Press功能 FunctionCtrl+F4, Ctrl+W关闭编辑器 Close editorCtrl+K F关闭文件夹 Close folderCtrl+\拆分编辑器 Split editorCtrl+ 1 / 2 / 3聚焦到第1，第2或第3编辑器组 Focus into 1st, 2nd or 3rd editor groupCtrl+K Ctrl+ ←/→聚焦到上一个/下一个编辑器组 Focus into previous/next editor groupCtrl+Shift+PgUp / PgDown向左/向右移动编辑器 Move editor left/rightCtrl+K ← / →移动活动编辑器组 Move active editor group文件管理 File management按 Press功能 FunctionCtrl+N新文件 New FileCtrl+O打开文件... Open File...Ctrl+S保存 SaveCtrl+Shift+S另存为... Save As...Ctrl+K S全部保存 Save AllCtrl+F4关闭 CloseCtrl+K Ctrl+W关闭所有 Close AllCtrl+Shift+T重新打开关闭的编辑器 Reopen closed editorCtrl+K输入保持打开 Enter Keep OpenCtrl+Tab打开下一个 Open nextCtrl+Shift+Tab打开上一个 Open previousCtrl+K P复制活动文件的路径 Copy path of active fileCtrl+K R显示资源管理器中的活动文件 Reveal active file in ExplorerCtrl+K O显示新窗口/实例中的活动文件 Show active file in new window/instance显示 Display按 Press功能 FunctionF11切换全屏 Toggle full screenShift+Alt+1切换编辑器布局 Toggle editor layoutCtrl+ = / -放大/缩小 Zoom in/outCtrl+B切换侧栏可见性 Toggle Sidebar visibilityCtrl+Shift+E显示浏览器/切换焦点 Show Explorer / Toggle focusCtrl+Shift+F显示搜索 Show SearchCtrl+Shift+G显示Git Show GitCtrl+Shift+D显示调试 Show DebugCtrl+Shift+X显示扩展 Show ExtensionsCtrl+Shift+H替换文件 Replace in filesCtrl+Shift+J切换搜索详细信息 Toggle Search detailsCtrl+Shift+C打开新命令提示符/终端 Open new command prompt/terminalCtrl+Shift+U显示输出面板 Show Output panelCtrl+Shift+V切换Markdown预览 Toggle Markdown previewCtrl+K V从旁边打开Markdown预览 Open Markdown preview to the side调试 Debug按 Press功能 FunctionF9切换断点 Toggle breakpointF5开始/继续 Start/ContinueShift+F5停止 StopF11 / Shift+F11下一步/上一步 Step into/outF10跳过 Step overCtrl+K Ctrl+I显示悬停 Show hover集成终端 Integrated terminal按 Press功能 FunctionCtrl+`显示集成终端 Show integrated terminalCtrl+Shift+`创建新终端 Create new terminalCtrl+Shift+C复制选定 Copy selectionCtrl+Shift+V粘贴到活动端子 Paste into active terminalCtrl+↑ / ↓向上/向下滚动 Scroll up/downShift+PgUp / PgDown向上/向下滚动页面 Scroll page up/downCtrl+Home / End滚动到顶部/底部 Scroll to top/bottom
Introduction<?php namespace Carbon; class Carbon extends \DateTime { // code here }use Carbon\Carbon;We also provide CarbonImmutable class extending DateTimeImmutable. The same methods are available on both classes but when you use a modifier on a Carbon instance, it modifies and returns the same instance, when you use it on CarbonImmutable, it returns a new instances with the new value.<?php $mutable = Carbon::now(); $immutable = CarbonImmutable::now(); $modifiedMutable = $mutable->add(1, 'day'); $modifiedImmutable = CarbonImmutable::now()->add(1, 'day'); var_dump($modifiedMutable === $mutable); // bool(true) var_dump($mutable->isoFormat('dddd D')); // string(11) "Saturday 22" var_dump($modifiedMutable->isoFormat('dddd D')); // string(11) "Saturday 22" // So it means $mutable and $modifiedMutable are the same object // both set to now + 1 day. var_dump($modifiedImmutable === $immutable); // bool(false) var_dump($immutable->isoFormat('dddd D')); // string(9) "Friday 21" var_dump($modifiedImmutable->isoFormat('dddd D')); // string(11) "Saturday 22" // While $immutable is still set to now and cannot be changed and // $modifiedImmutable is a new instance created from $immutable // set to now + 1 day. $mutable = CarbonImmutable::now()->toMutable(); var_dump($mutable->isMutable()); // bool(true) var_dump($mutable->isImmutable()); // bool(false) $immutable = Carbon::now()->toImmutable(); var_dump($immutable->isMutable()); // bool(false) var_dump($immutable->isImmutable()); // bool(true)Carbon has all of the functions inherited from the base DateTime class. This approach allows you to access the base functionality such as modify, format or diff.<?php $dtToronto = Carbon::create(2012, 1, 1, 0, 0, 0, 'America/Toronto'); $dtVancouver = Carbon::create(2012, 1, 1, 0, 0, 0, 'America/Vancouver'); // Try to replace the 4th number (hours) or the last argument (timezone) with // Europe/Paris for example and see the actual result on the right hand. // It's alive! echo $dtVancouver->diffInHours($dtToronto); // 3 // Now, try to double-click on "diffInHours" or "create" to open // the References panel. // Once the references panel is open, you can use the search field to // filter the list or click the (<) button to close it.Instantiation$carbon = new Carbon(); // equivalent to Carbon::now() $carbon = new Carbon('first day of January 2008', 'America/Vancouver'); echo get_class($carbon); // 'Carbon\Carbon' $carbon = new Carbon(new DateTime('first day of January 2008'), new DateTimeZone('America/Vancouver')); // equivalent to previous instance$now = Carbon::now(); // will use timezone as set with date_default_timezone_set // PS: we recommend you to work with UTC as default timezone and only use // other timezones (such as the user timezone) on display $nowInLondonTz = Carbon::now(new DateTimeZone('Europe/London')); // or just pass the timezone as a string $nowInLondonTz = Carbon::now('Europe/London'); echo $nowInLondonTz->tzName; // Europe/London echo "\n"; // or to create a date with a custom fixed timezone offset $date = Carbon::now('+13:30'); echo $date->tzName; // +13:30 echo "\n"; // Get/set minutes offset from UTC echo $date->utcOffset(); // 810 echo "\n"; $date->utcOffset(180); echo $date->tzName; // +03:00 echo "\n"; echo $date->utcOffset(); // 180If you really love your fluid method calls and get frustrated by the extra line or ugly pair of brackets necessary when using the constructor you'll enjoy the parse method.echo (new Carbon('first day of December 2008'))->addWeeks(2); // 2008-12-15 00:00:00 echo "\n"; echo Carbon::parse('first day of December 2008')->addWeeks(2); // 2008-12-15 00:00:00The string passed to Carbon::parse or to new Carbon can represent a relative time (next sunday, tomorrow, first day of next month, last year) or an absolute time (first day of December 2008, 2017-01-06). You can test if a string will produce a relative or absolute date with Carbon::hasRelativeKeywords().$string = 'first day of next month'; if (strtotime($string) === false) { echo "'$string' is not a valid date/time string."; } elseif (Carbon::hasRelativeKeywords($string)) { echo "'$string' is a relative valid date/time string, it will returns different dates depending on the current date."; } else { echo "'$string' is an absolute date/time string, it will always returns the same date."; }To accompany now(), a few other static instantiation helpers exist to create widely known instances. The only thing to really notice here is that today(), tomorrow() and yesterday(), besides behaving as expected, all accept a timezone parameter and each has their time value set to 00:00:00.$now = Carbon::now(); echo $now; // 2023-04-21 08:24:04 echo "\n"; $today = Carbon::today(); echo $today; // 2023-04-21 00:00:00 echo "\n"; $tomorrow = Carbon::tomorrow('Europe/London'); echo $tomorrow; // 2023-04-22 00:00:00 echo "\n"; $yesterday = Carbon::yesterday(); echo $yesterday; // 2023-04-20 00:00:00$year = 2000; $month = 4; $day = 19; $hour = 20; $minute = 30; $second = 15; $tz = 'Europe/Madrid'; echo Carbon::createFromDate($year, $month, $day, $tz)."\n"; echo Carbon::createMidnightDate($year, $month, $day, $tz)."\n"; echo Carbon::createFromTime($hour, $minute, $second, $tz)."\n"; echo Carbon::createFromTimeString("$hour:$minute:$second", $tz)."\n"; echo Carbon::create($year, $month, $day, $hour, $minute, $second, $tz)."\n";Most of the static create functions allow you to provide as many or as few arguments as you want and will provide default values for all others. Generally default values are the current date, time or timezone. Higher values will wrap appropriately but invalid values will throw an InvalidArgumentException with an informative message. The message is obtained from an DateTime::getLastErrors() call.$year = 2000; $month = 4; $day = 19; $hour = 20; $minute = 30; $second = 15; $tz = 'Asia/Shanghai'; echo Carbon::createFromDate($year, $month, $day, $tz) . "\n"; echo Carbon::createMidnightDate($year, $month, $day, $tz) . "\n"; echo Carbon::createFromTime($hour, $minute, $second, $tz) . "\n"; echo Carbon::createFromTimeString("$hour:$minute:$second", $tz) . "\n"; echo Carbon::create($year, $month, $day, $hour, $minute, $second, $tz) . "\n"; //2000-04-19 15:45:41 //2000-04-19 00:00:00 //2023-05-15 20:30:15 //2023-05-15 20:30:15 //2000-04-19 20:30:15createFromDate() will default the time to now. createFromTime() will default the date to today. create() will default any null parameter to the current respective value. As before, the $tz defaults to the current timezone and otherwise can be a DateTimeZone instance or simply a string timezone value. The only special case is for create() that has minimum value as default for missing argument but default on current value when you pass explicitly null.masThisYear = Carbon::createFromDate(null, 12, 25); // Year defaults to current year $Y2K = Carbon::create(2000, 1, 1, 0, 0, 0); // equivalent to Carbon::createMidnightDate(2000, 1, 1) $alsoY2K = Carbon::create(1999, 12, 31, 24); $noonLondonTz = Carbon::createFromTime(12, 0, 0, 'Europe/London'); $teaTime = Carbon::createFromTimeString('17:00:00', 'Europe/London'); try { Carbon::create(1975, 5, 21, 22, -2, 0); } catch(InvalidArgumentException $x) { echo $x->getMessage(); } // minute must be between 0 and 99, -2 given // Be careful, as Carbon::createFromDate() default values to current date, it can trigger overflow: // For example, if we are the 15th of June 2020, the following will set the date on 15: Carbon::createFromDate(2019, 4); // 2019-04-15 // If we are the 31th of October, as 31th April does not exist, it overflows to May: Carbon::createFromDate(2019, 4); // 2019-05-01 // That's why you simply should not use Carbon::createFromDate() with only 2 parameters (1 or 3 are safe, but no 2)Create exceptions occurs on such negative values but not on overflow, to get exceptions on overflow, use createSafe()echo Carbon::create(2000, 1, 35, 13, 0, 0); // 2000-02-04 13:00:00 echo "\n"; try { Carbon::createSafe(2000, 1, 35, 13, 0, 0); } catch (\Carbon\Exceptions\InvalidDateException $exp) { echo $exp->getMessage(); } // day : 35 is not a valid value.Note 1: 2018-02-29 also throws an exception while 2020-02-29 does not since 2020 is a leap year.Note 2: Carbon::createSafe(2014, 3, 30, 1, 30, 0, 'Europe/London') also produces an exception as this time is in an hour skipped by the daylight saving time.Note 3: The PHP native API allow consider there is a year 0 between -1 and 1 even if it doesn't regarding to Gregorian calendar. That's why years lower than 1 will throw an exception using createSafe. Check isValid() for year-0 detection.Carbon::createFromFormat($format, $time, $tz);createFromFormat() is mostly a wrapper for the base php function DateTime::createFromFormat. The difference being again the $tz argument can be a DateTimeZone instance or a string timezone value. Also, if there are errors with the format this function will call the DateTime::getLastErrors() method and then throw a InvalidArgumentException with the errors as the message.echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22')->toDateTimeString(); // 1975-05-21 22:00:00You can test if a date matches a format for createFromFormat() (e.g. date/time components, modifiers or separators) using Carbon::hasFormatWithModifiers() or Carbon::canBeCreatedFromFormat() which also ensure data is actually enough to create an instance.var_dump(Carbon::hasFormatWithModifiers('21/05/1975', 'd#m#Y!')); // bool(true) // As 21 is too high for a month number and day is expected to be formatted "05": var_dump(Carbon::hasFormatWithModifiers('5/21/1975', 'd#m#Y!')); // bool(false) // 5 is ok for N format: var_dump(Carbon::hasFormatWithModifiers('5', 'N')); // bool(true) // but not enough to create an instance: var_dump(Carbon::canBeCreatedFromFormat('5', 'N')); // bool(false) // Both hasFormatWithModifiers() and hasFormat() exist because // hasFormat() does not interpret modifiers, it checks strictly if ->format() could have produce the given // string with the given format: var_dump(Carbon::hasFormat('21/05/1975', 'd#m#Y!')); // bool(false) var_dump(Carbon::hasFormat('21#05#1975!', 'd#m#Y!')); // bool(true)You can create instances from unix timestamps. createFromTimestamp() create a Carbon instance equal to the given timestamp and will set the timezone as well or default it to the current timezone. createFromTimestampUTC(), is different in that the timezone will remain UTC (GMT+00:00), it's equivalent to Carbon::parse('@'.$timestamp) but it supports int, float or string containing one or more numbers (like the one produced by microtime()) so it can also set microseconds with no precision lost. The third, createFromTimestampMs(), accepts a timestamp in milliseconds instead of seconds. Negative timestamps are also allowed.echo Carbon::createFromTimestamp(-1)->toDateTimeString(); // 1969-12-31 23:59:59 echo Carbon::createFromTimestamp(-1.5, 'Europe/London')->toDateTimeString(); // 1970-01-01 00:59:58 echo Carbon::createFromTimestampUTC(-1)->toDateTimeString(); // 1969-12-31 23:59:59 echo Carbon::createFromTimestamp('1601735792.198956', 'Europe/London')->format('Y-m-d\TH:i:s.uP'); // 2020-10-03T15:36:32.198956+01:00 echo Carbon::createFromTimestampUTC('0.198956 1601735792')->format('Y-m-d\TH:i:s.uP'); // 2020-10-03T14:36:32.198956+00:00 echo Carbon::createFromTimestampMs(1)->format('Y-m-d\TH:i:s.uP'); // 1970-01-01T00:00:00.001000+00:00 echo Carbon::createFromTimestampMs('1601735792198.956', 'Europe/London')->format('Y-m-d\TH:i:s.uP'); // 2020-10-03T15:36:32.198956+01:00 echo Carbon::createFromTimestampMsUTC('0.956 1601735792198')->format('Y-m-d\TH:i:s.uP'); // 2020-10-03T14:36:32.198956+00:00You can also create a copy() of an existing Carbon instance. As expected the date, time and timezone values are all copied to the new instance.$dt = Carbon::now(); echo $dt->diffInYears($dt->copy()->addYear()); // 1 // $dt was unchanged and still holds the value of Carbon:now() // Without ->copy() it would return 0 because addYear() modify $dt so // diffInYears() compare $dt with itself: echo $dt->diffInYears($dt->addYear()); // 0 // Note that this would not happen neither with CarbonImmutable // When immutable, any add/sub methods return a new instance: $dt = CarbonImmutable::now(); echo $dt->diffInYears($dt->addYear()); // 1 // Last, when your variable can be either a Carbon or CarbonImmutable, // You can use avoidMutation() which will copy() only if the given date // is mutable: echo $dt->diffInYears($dt->avoidMutation()->addYear()); // 1You can use nowWithSameTz() on an existing Carbon instance to get a new instance at now in the same timezone.$meeting = Carbon::createFromTime(19, 15, 00, 'Africa/Johannesburg'); // 19:15 in Johannesburg echo 'Meeting starts at '.$meeting->format('H:i').' in Johannesburg.'; // Meeting starts at 19:15 in Johannesburg. // now in Johannesburg echo "It's ".$meeting->nowWithSameTz()->format('H:i').' right now in Johannesburg.'; // It's 10:24 right now in Johannesburg.Finally, if you find yourself inheriting a \DateTime instance from another library, fear not! You can create a Carbon instance via a friendly instance() method. Or use the even more flexible method make() which can return a new Carbon instance from a DateTime, Carbon or from a string, else it just returns null.$dt = new \DateTime('first day of January 2008'); // <== instance from another API $carbon = Carbon::instance($dt); echo get_class($carbon); // 'Carbon\Carbon' echo $carbon->toDateTimeString(); // 2008-01-01 00:00:00Ever need to loop through some dates to find the earliest or latest date? Didn't know what to set your initial maximum/minimum values to? There are now two helpers for this to make your decision simple:echo Carbon::maxValue(); // '9999-12-31 23:59:59' echo Carbon::minValue(); // '0001-01-01 00:00:00'GettersThe getters are implemented via PHP's __get() method. This enables you to access the value as if it was a property rather than a function call.$dt = Carbon::parse('2012-10-5 23:26:11.123789'); // These getters specifically return integers, ie intval() var_dump($dt->year); // int(2012) var_dump($dt->month); // int(10) var_dump($dt->day); // int(5) var_dump($dt->hour); // int(23) var_dump($dt->minute); // int(26) var_dump($dt->second); // int(11) var_dump($dt->micro); // int(123789) // dayOfWeek returns a number between 0 (sunday) and 6 (saturday) var_dump($dt->dayOfWeek); // int(5) // dayOfWeekIso returns a number between 1 (monday) and 7 (sunday) var_dump($dt->dayOfWeekIso); // int(5) var_dump($dt->englishDayOfWeek); // string(6) "Friday" var_dump($dt->shortEnglishDayOfWeek); // string(3) "Fri" var_dump($dt->locale('de')->dayName); // string(7) "Freitag" var_dump($dt->locale('de')->shortDayName); // string(3) "Fr." var_dump($dt->locale('de')->minDayName); // string(2) "Fr" var_dump($dt->englishMonth); // string(7) "October" var_dump($dt->shortEnglishMonth); // string(3) "Oct" var_dump($dt->locale('de')->monthName); // string(7) "Oktober" var_dump($dt->locale('de')->shortMonthName); // string(3) "Okt" // Following are deprecated, locale* and shortLocale* properties // are translated using formatLocalized() based on LC_TIME language. setlocale(LC_TIME, 'German'); var_dump($dt->localeDayOfWeek); // Deprecated: Function strftime() is deprecated in C:\Users\kylek\PhpstormProjects\CarbonDoc\vendor\nesbot\carbon\src\Carbon\Traits\Date.php on line 1894 string(7) "Freitag" var_dump($dt->shortLocaleDayOfWeek); // Deprecated: Function strftime() is deprecated in C:\Users\kylek\PhpstormProjects\CarbonDoc\vendor\nesbot\carbon\src\Carbon\Traits\Date.php on line 1894 string(2) "Fr" var_dump($dt->localeMonth); // Deprecated: Function strftime() is deprecated in C:\Users\kylek\PhpstormProjects\CarbonDoc\vendor\nesbot\carbon\src\Carbon\Traits\Date.php on line 1894 string(7) "Oktober" var_dump($dt->shortLocaleMonth); // Deprecated: Function strftime() is deprecated in C:\Users\kylek\PhpstormProjects\CarbonDoc\vendor\nesbot\carbon\src\Carbon\Traits\Date.php on line 1894 string(3) "Okt" setlocale(LC_TIME, ''); var_dump($dt->dayOfYear); // int(279) var_dump($dt->weekNumberInMonth); // int(1) // weekNumberInMonth consider weeks from monday to sunday, so the week 1 will // contain 1 day if the month start with a sunday, and up to 7 if it starts with a monday var_dump($dt->weekOfMonth); // int(1) // weekOfMonth will returns 1 for the 7 first days of the month, then 2 from the 8th to // the 14th, 3 from the 15th to the 21st, 4 from 22nd to 28th and 5 above var_dump($dt->weekOfYear); // int(40) var_dump($dt->daysInMonth); // int(31) var_dump($dt->timestamp); // int(1349479571) var_dump($dt->getTimestamp()); // int(1349479571) // Millisecond-precise timestamp as int var_dump($dt->getTimestampMs()); // int(1349479571124) // Millisecond-precise timestamp as float (useful to pass it to JavaScript) var_dump($dt->valueOf()); // float(1349479571124) // Custom-precision timestamp var_dump($dt->getPreciseTimestamp(6)); // float(1349479571123789) var_dump(Carbon::createFromDate(1975, 5, 21)->age); // int(47) calculated vs now in the same tz var_dump($dt->quarter); // int(4) // Returns an int of seconds difference from UTC (+/- sign included) var_dump(Carbon::createFromTimestampUTC(0)->offset); // int(0) var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->offset); // int(3600) var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->getOffset()); // int(3600) // Returns an int of hours difference from UTC (+/- sign included) var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->offsetMinutes); // int(60) var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->offsetHours); // int(1) // Returns timezone offset as string var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->getOffsetString()); // string(6) "+01:00" // Returns timezone as CarbonTimeZone var_dump(Carbon::createFromTimestamp(0, 'Europe/Paris')->getTimezone()); /* object(Carbon\CarbonTimeZone)#12335 (2) { ["timezone_type"]=> int(3) ["timezone"]=> string(12) "Europe/Paris" } */ // Indicates if day light savings time is on var_dump(Carbon::createFromDate(2012, 1, 1)->dst); // bool(false) var_dump(Carbon::createFromDate(2012, 9, 1)->dst); // bool(false) var_dump(Carbon::createFromDate(2012, 9, 1)->isDST()); // bool(false) // Indicates if the instance is in the same timezone as the local timezone var_dump(Carbon::now()->local); // bool(true) var_dump(Carbon::now('America/Vancouver')->local); // bool(false) var_dump(Carbon::now()->isLocal()); // bool(true) var_dump(Carbon::now('America/Vancouver')->isLocal()); // bool(false) var_dump(Carbon::now()->isUtc()); // bool(true) var_dump(Carbon::now('America/Vancouver')->isUtc()); // bool(false) // can also be written ->isUTC() // Indicates if the instance is in the UTC timezone var_dump(Carbon::now()->utc); // bool(true) // London is not UTC on summer time var_dump(Carbon::parse('2018-10-01', 'Europe/London')->utc); // bool(false) // London is UTC on winter time var_dump(Carbon::parse('2018-11-01', 'Europe/London')->utc); // bool(true) var_dump(Carbon::createFromTimestampUTC(0)->utc); // bool(true) // Gets the DateTimeZone instance echo get_class(Carbon::now()->timezone); // Carbon\CarbonTimeZone echo "\n"; echo get_class(Carbon::now()->tz); // Carbon\CarbonTimeZone echo "\n"; // Gets the DateTimeZone instance name, shortcut for ->timezone->getName() echo Carbon::now()->timezoneName; // UTC echo "\n"; echo Carbon::now()->tzName; // UTC echo "\n"; // You can get any property dynamically too: $unit = 'second'; var_dump(Carbon::now()->get($unit)); // int(5) // equivalent to: var_dump(Carbon::now()->$unit); // int(5) // If you have plural unit name, use singularUnit() $unit = Carbon::singularUnit('seconds'); var_dump(Carbon::now()->get($unit)); // int(5) // Prefer using singularUnit() because some plurals are not the word with S: var_dump(Carbon::pluralUnit('century')); // string(9) "centuries" var_dump(Carbon::pluralUnit('millennium')); // string(9) "millennia"SettersThe following setters are implemented via PHP's __set() method. Its good to take note here that none of the setters, with the obvious exception of explicitly setting the timezone, will change the timezone of the instance. Specifically, setting the timestamp will not set the corresponding timezone to UTC.$dt = Carbon::now(); $dt->year = 1975; $dt->month = 13; // would force year++ and month = 1 $dt->month = 5; $dt->day = 21; $dt->hour = 22; $dt->minute = 32; $dt->second = 5; $dt->timestamp = 169957925; // This will not change the timezone // Same as: $dt->setTimestamp(169957925); $dt->timestamp(169957925); // Set the timezone via DateTimeZone instance or string $dt->tz = new DateTimeZone('Europe/London'); $dt->tz = 'Europe/London'; // The ->timezone is also available for backward compatibility but // it will be overridden by native php DateTime class as soon as // the object is dump (passed foreach, serialize, var_export, clone, etc.) // making the Carbon setter inefficient, if it happen, you can cleanup // those overridden properties by calling ->cleanupDumpProperties() on // the instance, but we rather recommend to simply use ->tz instead // of ->timezone everywhere. // verbose way: $dt->setYear(2001); echo $dt->year; // 2001 echo "\n"; // set/get method: $dt->year(2002); echo $dt->year(); // 0000-05-22 03:32:05 echo "\n"; // dynamic way: $dt->set('year', 2003); echo $dt->get('year'); // 2003 echo "\n"; // these methods exist for every units even for calculated properties such as: echo $dt->dayOfYear(35)->format('Y-m-d'); // 2003-02-04Weeks$en = CarbonImmutable::now()->locale('en_US'); $ar = CarbonImmutable::now()->locale('ar'); var_dump($en->firstWeekDay); // int(0) var_dump($en->lastWeekDay); // int(6) var_dump($en->startOfWeek()->format('Y-m-d H:i')); // string(16) "2023-04-16 00:00" var_dump($en->endOfWeek()->format('Y-m-d H:i')); // string(16) "2023-04-22 23:59" echo "-----------\n"; // We still can force to use an other day as start/end of week $start = $en->startOfWeek(Carbon::TUESDAY); $end = $en->endOfWeek(Carbon::MONDAY); var_dump($start->format('Y-m-d H:i')); // string(16) "2023-04-18 00:00" var_dump($end->format('Y-m-d H:i')); // string(16) "2023-04-24 23:59" echo "-----------\n"; var_dump($ar->firstWeekDay); // int(6) var_dump($ar->lastWeekDay); // int(5) var_dump($ar->startOfWeek()->format('Y-m-d H:i')); // string(16) "2023-04-15 00:00" var_dump($ar->endOfWeek()->format('Y-m-d H:i')); // string(16) "2023-04-21 23:59" $en = CarbonImmutable::parse('2015-02-05'); // use en_US as default locale echo "-----------\n"; var_dump($en->weeksInYear()); // int(52) var_dump($en->isoWeeksInYear()); // int(53) $en = CarbonImmutable::parse('2017-02-05'); echo "-----------\n"; var_dump($en->week()); // int(6) var_dump($en->isoWeek()); // int(5) var_dump($en->week(1)->format('Y-m-d H:i')); // string(16) "2017-01-01 00:00" var_dump($en->isoWeek(1)->format('Y-m-d H:i')); // string(16) "2017-01-08 00:00" // weekday/isoWeekday are meant to be used with days constants var_dump($en->weekday()); // int(0) var_dump($en->isoWeekday()); // int(7) var_dump($en->weekday(CarbonInterface::WEDNESDAY) ->format('Y-m-d H:i')); // string(16) "2017-02-08 00:00" var_dump($en->isoWeekday(CarbonInterface::WEDNESDAY) ->format('Y-m-d H:i')); // string(16) "2017-02-01 00:00" // getDaysFromStartOfWeek/setDaysFromStartOfWeek return and take a number of days // taking the current locale into account $date = CarbonImmutable::parse('2022-12-05')->locale('en_US'); var_dump($date->getDaysFromStartOfWeek()); // int(1) $date = CarbonImmutable::parse('2022-12-05')->locale('de_AT'); var_dump($date->getDaysFromStartOfWeek()); // int(0) var_dump($date->setDaysFromStartOfWeek(3)->format('Y-m-d')); // string(10) "2022-12-08" // Or specify explicitly the first day of week var_dump($date->setDaysFromStartOfWeek(3, CarbonInterface::SUNDAY)->format('Y-m-d')); // string(10) "2022-12-07" $en = CarbonImmutable::parse('2017-01-01'); echo "-----------\n"; var_dump($en->weekYear()); // int(2017) var_dump($en->isoWeekYear()); // int(2016) var_dump($en->weekYear(2016)->format('Y-m-d H:i')); // string(16) "2015-12-27 00:00" var_dump($en->isoWeekYear(2016)->format('Y-m-d H:i')); // string(16) "2017-01-01 00:00" var_dump($en->weekYear(2015)->format('Y-m-d H:i')); // string(16) "2014-12-28 00:00" var_dump($en->isoWeekYear(2015)->format('Y-m-d H:i')); // string(16) "2015-12-27 00:00" // Note you still can force first day of week and year to use: $en = CarbonImmutable::parse('2017-01-01'); echo "-----------\n"; var_dump($en->weeksInYear(null, 6, 12)); // int(52) var_dump($en->isoWeeksInYear(null, 6, 12)); // int(52) var_dump($en->week(null, 6, 12)); // int(52) var_dump($en->isoWeek(null, 6, 12)); // int(52) var_dump($en->weekYear(null, 6, 12)); // int(2016) var_dump($en->isoWeekYear(null, 6, 12)); // int(2016) var_dump($en->weekYear(2016, 6, 12)->format('Y-m-d H:i')); // string(16) "2017-01-01 00:00" var_dump($en->isoWeekYear(2016, 6, 12)->format('Y-m-d H:i')); // string(16) "2017-01-01 00:00" // Then you can see using a method or its ISO variant return identical resultsFluent SettersYou can call any base unit as a setter or some grouped setters:$dt = Carbon::now(); $dt->year(1975)->month(5)->day(21)->hour(22)->minute(32)->second(5)->toDateTimeString(); $dt->setDate(1975, 5, 21)->setTime(22, 32, 5)->toDateTimeString(); $dt->setDate(1975, 5, 21)->setTimeFromTimeString('22:32:05')->toDateTimeString(); $dt->setDateTime(1975, 5, 21, 22, 32, 5)->toDateTimeString(); // All allow microsecond as optional argument $dt->year(1975)->month(5)->day(21)->hour(22)->minute(32)->second(5)->microsecond(123456)->toDateTimeString(); $dt->setDate(1975, 5, 21)->setTime(22, 32, 5, 123456)->toDateTimeString(); $dt->setDate(1975, 5, 21)->setTimeFromTimeString('22:32:05.123456')->toDateTimeString(); $dt->setDateTime(1975, 5, 21, 22, 32, 5, 123456)->toDateTimeString(); $dt->timestamp(169957925); // Note: timestamps are UTC but do not change the date timezone $dt->timezone('Europe/London')->tz('America/Toronto')->setTimezone('America/Vancouver');You also can set date and time separately from other DateTime/Carbon objects:$source1 = new Carbon('2010-05-16 22:40:10.1'); $dt = new Carbon('2001-01-01 01:01:01.2'); $dt->setTimeFrom($source1); echo $dt; // 2001-01-01 22:40:10 $source2 = new DateTime('2013-09-01 09:22:56.2'); $dt->setDateFrom($source2); echo $dt; // 2013-09-01 22:40:10 $dt->setDateTimeFrom($source2); // set date and time including microseconds // bot not settings as locale, timezone, options.IsSetvar_dump(isset(Carbon::now()->iDoNotExist)); // bool(false) var_dump(isset(Carbon::now()->hour)); // bool(true) var_dump(empty(Carbon::now()->iDoNotExist)); // bool(true) var_dump(empty(Carbon::now()->year)); // bool(false)String FormattingAll of the available toXXXString() methods rely on the base class method DateTime::format(). You'll notice the __toString() method is defined which allows a Carbon instance to be printed as a pretty date time string when used in a string context.$dt = Carbon::create(1975, 12, 25, 14, 15, 16); var_dump($dt->toDateTimeString() == $dt); // bool(true) => uses __toString() echo $dt->toDateString(); // 1975-12-25 echo $dt->toFormattedDateString(); // Dec 25, 1975 echo $dt->toFormattedDayDateString(); // Thu, Dec 25, 1975 echo $dt->toTimeString(); // 14:15:16 echo $dt->toDateTimeString(); // 1975-12-25 14:15:16 echo $dt->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM // ... of course format() is still available echo $dt->format('l jS \\of F Y h:i:s A'); // Thursday 25th of December 1975 02:15:16 PM // The reverse hasFormat method allows you to test if a string looks like a given format var_dump(Carbon::hasFormat('Thursday 25th December 1975 02:15:16 PM', 'l jS F Y h:i:s A')); // bool(true)You can also set the default __toString() format (which defaults to Y-m-d H:i:s) thats used when type juggling occurs.echo $dt; // 1975-12-25 14:15:16 echo "\n"; $dt->settings([ 'toStringFormat' => 'jS \o\f F, Y g:i:s a', ]); echo $dt; // 25th of December, 1975 2:15:16 pm // As any setting, you can get the current value for a given date using: var_dump($dt->getSettings()); /* array(3) { ["toStringFormat"]=> string(20) "jS \o\f F, Y g:i:s a" ["locale"]=> string(2) "en" ["timezone"]=> string(3) "UTC" }*/As part of the settings 'toStringFormat' can be used in factories too. It also may be a closure, so you can run any code on string cast.If you use Carbon 1 or want to apply it globally as default format, you can use:$dt = Carbon::create(1975, 12, 25, 14, 15, 16); Carbon::setToStringFormat('jS \o\f F, Y g:i:s a'); echo $dt; // 25th of December, 1975 2:15:16 pm echo "\n"; Carbon::resetToStringFormat(); echo $dt; // 1975-12-25 14:15:16Note: For localization support see the Localization section.Common FormatsThe following are wrappers for the common formats provided in the DateTime class.$dt = Carbon::createFromFormat('Y-m-d H:i:s.u', '2019-02-01 03:45:27.612584'); // $dt->toAtomString() is the same as $dt->format(DateTime::ATOM); echo $dt->toAtomString(); // 2019-02-01T03:45:27+00:00 echo $dt->toCookieString(); // Friday, 01-Feb-2019 03:45:27 UTC echo $dt->toIso8601String(); // 2019-02-01T03:45:27+00:00 // Be aware we chose to use the full-extended format of the ISO 8601 norm // Natively, DateTime::ISO8601 format is not compatible with ISO-8601 as it // is explained here in the PHP documentation: // https://php.net/manual/class.datetime.php#datetime.constants.iso8601 // We consider it as a PHP mistake and chose not to provide method for this // format, but you still can use it this way: echo $dt->format(DateTime::ISO8601); // 2019-02-01T03:45:27+0000 echo $dt->toISOString(); // 2019-02-01T03:45:27.612584Z echo $dt->toJSON(); // 2019-02-01T03:45:27.612584Z echo $dt->toIso8601ZuluString(); // 2019-02-01T03:45:27Z echo $dt->toDateTimeLocalString(); // 2019-02-01T03:45:27 echo $dt->toRfc822String(); // Fri, 01 Feb 19 03:45:27 +0000 echo $dt->toRfc850String(); // Friday, 01-Feb-19 03:45:27 UTC echo $dt->toRfc1036String(); // Fri, 01 Feb 19 03:45:27 +0000 echo $dt->toRfc1123String(); // Fri, 01 Feb 2019 03:45:27 +0000 echo $dt->toRfc2822String(); // Fri, 01 Feb 2019 03:45:27 +0000 echo $dt->toRfc3339String(); // 2019-02-01T03:45:27+00:00 echo $dt->toRfc7231String(); // Fri, 01 Feb 2019 03:45:27 GMT echo $dt->toRssString(); // Fri, 01 Feb 2019 03:45:27 +0000 echo $dt->toW3cString(); // 2019-02-01T03:45:27+00:00Conversion$dt = Carbon::createFromFormat('Y-m-d H:i:s.u', '2019-02-01 03:45:27.612584'); var_dump($dt->toArray()); /* array(12) { ["year"]=> int(2019) ["month"]=> int(2) ["day"]=> int(1) ["dayOfWeek"]=> int(5) ["dayOfYear"]=> int(32) ["hour"]=> int(3) ["minute"]=> int(45) ["second"]=> int(27) ["micro"]=> int(612584) ["timestamp"]=> int(1548992727) ["formatted"]=> string(19) "2019-02-01 03:45:27" ["timezone"]=> object(Carbon\CarbonTimeZone)#12339 (2) { ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } } */ var_dump($dt->toObject()); /* object(stdClass)#12339 (12) { ["year"]=> int(2019) ["month"]=> int(2) ["day"]=> int(1) ["dayOfWeek"]=> int(5) ["dayOfYear"]=> int(32) ["hour"]=> int(3) ["minute"]=> int(45) ["second"]=> int(27) ["micro"]=> int(612584) ["timestamp"]=> int(1548992727) ["formatted"]=> string(19) "2019-02-01 03:45:27" ["timezone"]=> object(Carbon\CarbonTimeZone)#12335 (2) { ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } } */ var_dump($dt->toDate()); // Same as $dt->toDateTime() /* object(DateTime)#12339 (3) { ["date"]=> string(26) "2019-02-01 03:45:27.612584" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } */ // Note than both Carbon and CarbonImmutable can be cast // to both DateTime and DateTimeImmutable var_dump($dt->toDateTimeImmutable()); /* object(DateTimeImmutable)#12339 (3) { ["date"]=> string(26) "2019-02-01 03:45:27.612584" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } */ class MySubClass extends Carbon {} // MySubClass can be any class implementing CarbonInterface or a public static instance() method. $copy = $dt->cast(MySubClass::class); // Since 2.23.0, cast() can also take as argument any class that extend DateTime or DateTimeImmutable echo get_class($copy).': '.$copy; // Same as MySubClass::instance($dt) /* MySubClass: 2019-02-01 03:45:27 */You can use the method carbonize to transform many things into a Carbon instance based on a given source instance used as reference on need. It returns a new instance.$dt = Carbon::createFromFormat('Y-m-d H:i:s.u', '2019-02-01 03:45:27.612584', 'Europe/Paris'); // Can take a date string and will apply the timezone from reference object var_dump($dt->carbonize('2019-03-21')); /* array(2) { ["date"]=> string(26) "2019-03-21 00:00:00.000000" ["timezone"]=> string(12) "Europe/Paris" } */ // If you pass a DatePeriod or CarbonPeriod, it will copy the period start var_dump($dt->carbonize(CarbonPeriod::create('2019-12-10', '2020-01-05'))); /* array(2) { ["date"]=> string(26) "2019-12-10 00:00:00.000000" ["timezone"]=> string(3) "UTC" } */ // If you pass a DateInterval or CarbonInterval, it will add the interval to // the reference object var_dump($dt->carbonize(CarbonInterval::days(3))); /* array(2) { ["date"]=> string(26) "2019-02-04 03:45:27.612584" ["timezone"]=> string(12) "Europe/Paris" } */Comparisonecho Carbon::now()->tzName; // UTC $first = Carbon::create(2012, 9, 5, 23, 26, 11); $second = Carbon::create(2012, 9, 5, 20, 26, 11, 'America/Vancouver'); echo $first->toDateTimeString(); // 2012-09-05 23:26:11 echo $first->tzName; // UTC echo $second->toDateTimeString(); // 2012-09-05 20:26:11 echo $second->tzName; // America/Vancouver var_dump($first->equalTo($second)); // bool(false) // equalTo is also available on CarbonInterval and CarbonPeriod var_dump($first->notEqualTo($second)); // bool(true) // notEqualTo is also available on CarbonInterval and CarbonPeriod var_dump($first->greaterThan($second)); // bool(false) // greaterThan is also available on CarbonInterval var_dump($first->greaterThanOrEqualTo($second)); // bool(false) // greaterThanOrEqualTo is also available on CarbonInterval var_dump($first->lessThan($second)); // bool(true) // lessThan is also available on CarbonInterval var_dump($first->lessThanOrEqualTo($second)); // bool(true) // lessThanOrEqualTo is also available on CarbonInterval $first->setDateTime(2012, 1, 1, 0, 0, 0); $second->setDateTime(2012, 1, 1, 0, 0, 0); // Remember tz is 'America/Vancouver' var_dump($first->equalTo($second)); // bool(false) var_dump($first->notEqualTo($second)); // bool(true) var_dump($first->greaterThan($second)); // bool(false) var_dump($first->greaterThanOrEqualTo($second)); // bool(false) var_dump($first->lessThan($second)); // bool(true) var_dump($first->lessThanOrEqualTo($second)); // bool(true) // All have short hand aliases and PHP equivalent code: var_dump($first->eq($second)); // bool(false) var_dump($first->equalTo($second)); // bool(false) var_dump($first == $second); // bool(false) var_dump($first->ne($second)); // bool(true) var_dump($first->notEqualTo($second)); // bool(true) var_dump($first != $second); // bool(true) var_dump($first->gt($second)); // bool(false) var_dump($first->greaterThan($second)); // bool(false) var_dump($first->isAfter($second)); // bool(false) var_dump($first > $second); // bool(false) var_dump($first->gte($second)); // bool(false) var_dump($first->greaterThanOrEqualTo($second)); // bool(false) var_dump($first >= $second); // bool(false) var_dump($first->lt($second)); // bool(true) var_dump($first->lessThan($second)); // bool(true) var_dump($first->isBefore($second)); // bool(true) var_dump($first < $second); // bool(true) var_dump($first->lte($second)); // bool(true) var_dump($first->lessThanOrEqualTo($second)); // bool(true) var_dump($first <= $second); // bool(true)Those methods use natural comparisons offered by PHP $date1 == $date2 so all of them will ignore milli/micro-seconds before PHP 7.1, then take them into account starting with 7.1.To determine if the current instance is between two other instances you can use the aptly named between() method (or isBetween() alias). The third parameter indicates if an equal to comparison should be done. The default is true which determines if its between or equal to the boundaries.$first = Carbon::create(2012, 9, 5, 1); $second = Carbon::create(2012, 9, 5, 5); var_dump(Carbon::create(2012, 9, 5, 3)->between($first, $second)); // bool(true) var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second)); // bool(true) var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second, false)); // bool(false) var_dump(Carbon::create(2012, 9, 5, 5)->isBetween($first, $second, false)); // bool(false) // Rather than passing false as a third argument, you can use betweenIncluded and betweenExcluded var_dump(Carbon::create(2012, 9, 5, 5)->betweenIncluded($first, $second)); // bool(true) var_dump(Carbon::create(2012, 9, 5, 5)->betweenExcluded($first, $second)); // bool(false) // All those methods are also available on CarbonIntervalWoah! Did you forget min() and max() ? Nope. That is covered as well by the suitably named min() and max() methods or minimum() and maximum() aliases. As usual the default parameter is now if null is specified.$dt1 = Carbon::createMidnightDate(2012, 1, 1); $dt2 = Carbon::createMidnightDate(2014, 1, 30); echo $dt1->min($dt2); // 2012-01-01 00:00:00 echo $dt1->minimum($dt2); // 2012-01-01 00:00:00 // Also works with string echo $dt1->minimum('2014-01-30'); // 2012-01-01 00:00:00 $dt1 = Carbon::createMidnightDate(2012, 1, 1); $dt2 = Carbon::createMidnightDate(2014, 1, 30); echo $dt1->max($dt2); // 2014-01-30 00:00:00 echo $dt1->maximum($dt2); // 2014-01-30 00:00:00 // now is the default param $dt1 = Carbon::createMidnightDate(2000, 1, 1); echo $dt1->max(); // 2023-04-21 08:24:05 echo $dt1->maximum(); // 2023-04-21 08:24:05 // Remember min and max PHP native function work fine with dates too: echo max(Carbon::create('2002-03-15'), Carbon::create('2003-01-07'), Carbon::create('2002-08-25')); // 2003-01-07 00:00:00 echo min(Carbon::create('2002-03-15'), Carbon::create('2003-01-07'), Carbon::create('2002-08-25')); // 2002-03-15 00:00:00 // This way you can pass as many dates as you want and get no ambiguities about parameters order $dt1 = Carbon::createMidnightDate(2010, 4, 1); $dt2 = Carbon::createMidnightDate(2010, 3, 28); $dt3 = Carbon::createMidnightDate(2010, 4, 16); // returns the closest of two date (no matter before or after) echo $dt1->closest($dt2, $dt3); // 2010-03-28 00:00:00 echo $dt2->closest($dt1, $dt3); // 2010-04-01 00:00:00 echo $dt3->closest($dt2, $dt1); // 2010-04-01 00:00:00 // returns the farthest of two date (no matter before or after) echo $dt1->farthest($dt2, $dt3); // 2010-04-16 00:00:00 echo $dt2->farthest($dt1, $dt3); // 2010-04-16 00:00:00 echo $dt3->farthest($dt2, $dt1); // 2010-03-28 00:00:00To handle the most used cases there are some simple helper functions that hopefully are obvious from their names. For the methods that compare to now() (ex. isToday()) in some manner, the now() is created in the same timezone as the instance.$dt = Carbon::now(); $dt2 = Carbon::createFromDate(1987, 4, 23); $dt->isSameAs('w', $dt2); // w is the date of the week, so this will return true if $dt and $dt2 // the same day of week (both monday or both sunday, etc.) // you can use any format and combine as much as you want. $dt->isFuture(); $dt->isPast(); $dt->isSameYear($dt2); $dt->isCurrentYear(); $dt->isNextYear(); $dt->isLastYear(); $dt->isLongIsoYear(); // see https://en.wikipedia.org/wiki/ISO_8601#Week_dates Carbon::create(2015)->isLongYear(); // isLongIsoYear() check a given date, // while isLongYear() will ignore month/day and just check a given year number $dt->isLeapYear(); $dt->isSameQuarter($dt2); // same quarter of the same year of the given date $dt->isSameQuarter($dt2, false); // same quarter (3 months) no matter the year of the given date $dt->isCurrentQuarter(); $dt->isNextQuarter(); // date is in the next quarter $dt->isLastQuarter(); // in previous quarter $dt->isSameMonth($dt2); // same month of the same year of the given date $dt->isSameMonth($dt2, false); // same month no matter the year of the given date $dt->isCurrentMonth(); $dt->isNextMonth(); $dt->isLastMonth(); $dt->isWeekday(); $dt->isWeekend(); $dt->isMonday(); $dt->isTuesday(); $dt->isWednesday(); $dt->isThursday(); $dt->isFriday(); $dt->isSaturday(); $dt->isSunday(); $dt->isDayOfWeek(Carbon::SATURDAY); // is a saturday $dt->isLastOfMonth(); // is the last day of the month $dt->is('Sunday'); $dt->is('June'); $dt->is('2019'); $dt->is('12:23'); $dt->is('2 June 2019'); $dt->is('06-02'); $dt->isSameDay($dt2); // Same day of same month of same year $dt->isCurrentDay(); $dt->isYesterday(); $dt->isToday(); $dt->isTomorrow(); $dt->isNextWeek(); $dt->isLastWeek(); $dt->isSameHour($dt2); $dt->isCurrentHour(); $dt->isSameMinute($dt2); $dt->isCurrentMinute(); $dt->isSameSecond($dt2); $dt->isCurrentSecond(); $dt->isStartOfDay(); // check if hour is 00:00:00 $dt->isMidnight(); // check if hour is 00:00:00 (isStartOfDay alias) $dt->isEndOfDay(); // check if hour is 23:59:59 $dt->isMidday(); // check if hour is 12:00:00 (or other midday hour set with Carbon::setMidDayAt()) $born = Carbon::createFromDate(1987, 4, 23); $noCake = Carbon::createFromDate(2014, 9, 26); $yesCake = Carbon::createFromDate(2014, 4, 23); $overTheHill = Carbon::now()->subYears(50); var_dump($born->isBirthday($noCake)); // bool(false) var_dump($born->isBirthday($yesCake)); // bool(true) var_dump($overTheHill->isBirthday()); // bool(true) -> default compare it to today! // isCurrentX, isSameX, isNextX and isLastX are available for each unitAddition and SubtractionThe default DateTime provides a couple of different methods for easily adding and subtracting time. There is modify(), add() and sub(). change() is an enhanced version of modify() that can take magical date/time format string, 'last day of next month', that it parses and applies the modification while add() and sub() can take the same the same kind of string, intervals (DateInterval or CarbonInterval) or count+unit parameters. But you can still access the native methods of DateTime class using rawAdd() and rawSub().$dt = Carbon::create(2012, 1, 31, 0); echo $dt->toDateTimeString(); // 2012-01-31 00:00:00 echo $dt->addCenturies(5); // 2512-01-31 00:00:00 echo $dt->addCentury(); // 2612-01-31 00:00:00 echo $dt->subCentury(); // 2512-01-31 00:00:00 echo $dt->subCenturies(5); // 2012-01-31 00:00:00 echo $dt->addYears(5); // 2017-01-31 00:00:00 echo $dt->addYear(); // 2018-01-31 00:00:00 echo $dt->subYear(); // 2017-01-31 00:00:00 echo $dt->subYears(5); // 2012-01-31 00:00:00 echo $dt->addQuarters(2); // 2012-07-31 00:00:00 echo $dt->addQuarter(); // 2012-10-31 00:00:00 echo $dt->subQuarter(); // 2012-07-31 00:00:00 echo $dt->subQuarters(2); // 2012-01-31 00:00:00 echo $dt->addMonths(60); // 2017-01-31 00:00:00 echo $dt->addMonth(); // 2017-03-03 00:00:00 equivalent of $dt->month($dt->month + 1); so it wraps echo $dt->subMonth(); // 2017-02-03 00:00:00 echo $dt->subMonths(60); // 2012-02-03 00:00:00 echo $dt->addDays(29); // 2012-03-03 00:00:00 echo $dt->addDay(); // 2012-03-04 00:00:00 echo $dt->subDay(); // 2012-03-03 00:00:00 echo $dt->subDays(29); // 2012-02-03 00:00:00 echo $dt->addWeekdays(4); // 2012-02-09 00:00:00 echo $dt->addWeekday(); // 2012-02-10 00:00:00 echo $dt->subWeekday(); // 2012-02-09 00:00:00 echo $dt->subWeekdays(4); // 2012-02-03 00:00:00 echo $dt->addWeeks(3); // 2012-02-24 00:00:00 echo $dt->addWeek(); // 2012-03-02 00:00:00 echo $dt->subWeek(); // 2012-02-24 00:00:00 echo $dt->subWeeks(3); // 2012-02-03 00:00:00 echo $dt->addHours(24); // 2012-02-04 00:00:00 echo $dt->addHour(); // 2012-02-04 01:00:00 echo $dt->subHour(); // 2012-02-04 00:00:00 echo $dt->subHours(24); // 2012-02-03 00:00:00 echo $dt->addMinutes(61); // 2012-02-03 01:01:00 echo $dt->addMinute(); // 2012-02-03 01:02:00 echo $dt->subMinute(); // 2012-02-03 01:01:00 echo $dt->subMinutes(61); // 2012-02-03 00:00:00 echo $dt->addSeconds(61); // 2012-02-03 00:01:01 echo $dt->addSecond(); // 2012-02-03 00:01:02 echo $dt->subSecond(); // 2012-02-03 00:01:01 echo $dt->subSeconds(61); // 2012-02-03 00:00:00 echo $dt->addMilliseconds(61); // 2012-02-03 00:00:00 echo $dt->addMillisecond(); // 2012-02-03 00:00:00 echo $dt->subMillisecond(); // 2012-02-03 00:00:00 echo $dt->subMillisecond(61); // 2012-02-03 00:00:00 echo $dt->addMicroseconds(61); // 2012-02-03 00:00:00 echo $dt->addMicrosecond(); // 2012-02-03 00:00:00 echo $dt->subMicrosecond(); // 2012-02-03 00:00:00 echo $dt->subMicroseconds(61); // 2012-02-03 00:00:00 // and so on for any unit: millenium, century, decade, year, quarter, month, week, day, weekday, // hour, minute, second, microsecond. // Generic methods add/sub (or subtract alias) can take many different arguments: echo $dt->add(61, 'seconds'); // 2012-02-03 00:01:01 echo $dt->sub('1 day'); // 2012-02-02 00:01:01 echo $dt->add(CarbonInterval::months(2)); // 2012-04-02 00:01:01 echo $dt->subtract(new DateInterval('PT1H')); // 2012-04-01 23:01:01For fun you can also pass negative values to addXXX(), in fact that's how subXXX() is implemented.P.S. Don't worry if you forget and use addDay(5) or subYear(3), I have your back ;)By default, Carbon relies on the underlying parent class PHP DateTime behavior. As a result adding or subtracting months can overflow, example:$dt = CarbonImmutable::create(2017, 1, 31, 0); echo $dt->addMonth(); // 2017-03-03 00:00:00 echo "\n"; echo $dt->subMonths(2); // 2016-12-01 00:00:00Since Carbon 2, you can set a local overflow behavior for each instance:$dt = CarbonImmutable::create(2017, 1, 31, 0); $dt->settings([ 'monthOverflow' => false, ]); echo $dt->addMonth(); // 2017-02-28 00:00:00 echo "\n"; echo $dt->subMonths(2); // 2016-11-30 00:00:00This will apply for methods addMonth(s), subMonth(s), add($x, 'month'), sub($x, 'month') and equivalent quarter methods. But it won't apply for intervals objects or strings like add(CarbonInterval::month()) or add('1 month').Static helpers exist but are deprecated. If you're sure to need to apply global setting or work with version 1 of Carbon, check the overflow static helpers sectionYou also can use ->addMonthsNoOverflow, ->subMonthsNoOverflow, ->addMonthsWithOverflow and ->subMonthsWithOverflow (or the singular methods with no s to "month") to explicitly add/sub months with or without overflow no matter the current mode and the same for any bigger unit (quarter, year, decade, century, millennium).$dt = Carbon::createMidnightDate(2017, 1, 31)->settings([ 'monthOverflow' => false, ]); echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00 // plural addMonthsWithOverflow() method is also available echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00 // singular subMonthWithOverflow() method is also available echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00 // plural addMonthsNoOverflow() method is also available echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00 // singular subMonthNoOverflow() method is also available echo $dt->copy()->addMonth(); // 2017-02-28 00:00:00 echo $dt->copy()->subMonths(2); // 2016-11-30 00:00:00 $dt = Carbon::createMidnightDate(2017, 1, 31)->settings([ 'monthOverflow' => true, ]); echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00 echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00 echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00 echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00 echo $dt->copy()->addMonth(); // 2017-03-03 00:00:00 echo $dt->copy()->subMonths(2); // 2016-12-01 00:00:00The same is available for years.You also can control overflow for any unit when working with unknown inputs:$dt = CarbonImmutable::create(2018, 8, 30, 12, 00, 00); // Add hours without overflowing day echo $dt->addUnitNoOverflow('hour', 7, 'day'); // 2018-08-30 19:00:00 echo "\n"; echo $dt->addUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 23:59:59 echo "\n"; echo $dt->addUnitNoOverflow('hour', 48, 'day'); // 2018-08-30 23:59:59 echo "\n-------\n"; // Substract hours without overflowing day echo $dt->subUnitNoOverflow('hour', 7, 'day'); // 2018-08-30 05:00:00 echo "\n"; echo $dt->subUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 00:00:00 echo "\n"; echo $dt->subUnitNoOverflow('hour', 48, 'day'); // 2018-08-30 00:00:00 echo "\n-------\n"; // Set hours without overflowing day echo $dt->setUnitNoOverflow('hour', -7, 'day'); // 2018-08-30 00:00:00 echo "\n"; echo $dt->setUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 14:00:00 echo "\n"; echo $dt->setUnitNoOverflow('hour', 25, 'day'); // 2018-08-30 23:59:59 echo "\n-------\n"; // Adding hours without overflowing month echo $dt->addUnitNoOverflow('hour', 7, 'month'); // 2018-08-30 19:00:00 echo "\n"; echo $dt->addUnitNoOverflow('hour', 14, 'month'); // 2018-08-31 02:00:00 echo "\n"; echo $dt->addUnitNoOverflow('hour', 48, 'month'); // 2018-08-31 23:59:59Any modifiable unit can be passed as argument of those methods:$units = []; foreach (['millennium', 'century', 'decade', 'year', 'quarter', 'month', 'week', 'weekday', 'day', 'hour', 'minute', 'second', 'millisecond', 'microsecond'] as $unit) { $units[$unit] = Carbon::isModifiableUnit($unit); } echo json_encode($units, JSON_PRETTY_PRINT); /* { "millennium": true, "century": true, "decade": true, "year": true, "quarter": true, "month": true, "week": true, "weekday": true, "day": true, "hour": true, "minute": true, "second": true, "millisecond": true, "microsecond": true } */DifferenceAs Carbon extends DateTime it inherit its methods such as diff() that take a second date object as argument and returns a DateInterval instance.We also provide diffAsCarbonInterval() act like diff() but returns a CarbonInterval instance. Check CarbonInterval chapter for more information. Carbon add diff methods for each unit too such as diffInYears(), diffInMonths() and so on. diffAsCarbonInterval() and diffIn*() and floatDiffIn*() methods all can take 2 optional arguments: date to compare with (if missing, now is used instead), and an absolute boolean option (true by default) that make the method return an absolute value no matter which date is greater than the other. If set to false, it returns negative value when the instance the method is called on is greater than the compared date (first argument or now). Note that diff() prototype is different: its first argument (the date) is mandatory and its second argument (the absolute option) defaults to false.These functions always return the total difference expressed in the specified time requested. This differs from the base class diff() function where an interval of 122 seconds would be returned as 2 minutes and 2 seconds via a DateInterval instance. The diffInMinutes() function would simply return 2 while diffInSeconds() would return 122. All values are truncated and not rounded. Each function below has a default first parameter which is the Carbon instance to compare to, or null if you want to use now(). The 2nd parameter again is optional and indicates if you want the return value to be the absolute value or a relative value that might have a - (negative) sign if the passed in date is less than the current instance. This will default to true, return the absolute value.echo Carbon::now('America/Vancouver')->diffInSeconds(Carbon::now('Europe/London')); // 0 $dtOttawa = Carbon::createMidnightDate(2000, 1, 1, 'America/Toronto'); $dtVancouver = Carbon::createMidnightDate(2000, 1, 1, 'America/Vancouver'); echo $dtOttawa->diffInHours($dtVancouver); // 3 echo $dtVancouver->diffInHours($dtOttawa); // 3 echo $dtOttawa->diffInHours($dtVancouver, false); // 3 echo $dtVancouver->diffInHours($dtOttawa, false); // -3 $dt = Carbon::createMidnightDate(2012, 1, 31); echo $dt->diffInDays($dt->copy()->addMonth()); // 31 echo $dt->diffInDays($dt->copy()->subMonth(), false); // -31 $dt = Carbon::createMidnightDate(2012, 4, 30); echo $dt->diffInDays($dt->copy()->addMonth()); // 30 echo $dt->diffInDays($dt->copy()->addWeek()); // 7 $dt = Carbon::createMidnightDate(2012, 1, 1); echo $dt->diffInMinutes($dt->copy()->addSeconds(59)); // 0 echo $dt->diffInMinutes($dt->copy()->addSeconds(60)); // 1 echo $dt->diffInMinutes($dt->copy()->addSeconds(119)); // 1 echo $dt->diffInMinutes($dt->copy()->addSeconds(120)); // 2 echo $dt->addSeconds(120)->secondsSinceMidnight(); // 120 $interval = $dt->diffAsCarbonInterval($dt->copy()->subYears(3), false); // diffAsCarbonInterval use same arguments as diff($other, $absolute) // (native method from \DateTime) // except $absolute is true by default for diffAsCarbonInterval and false for diff // $absolute parameter allow to get signed value if false, or always positive if true echo ($interval->invert ? 'minus ' : 'plus ') . $interval->years; // minus 3These methods have int-truncated results. That means diffInMinutes returns 1 for any difference between 1 included and 2 excluded. But same methods are available for float results:echo Carbon::parse('06:01:23.252987')->floatDiffInSeconds('06:02:34.321450'); // 71.068463 echo Carbon::parse('06:01:23')->floatDiffInMinutes('06:02:34'); // 1.1833333333333 echo Carbon::parse('06:01:23')->floatDiffInHours('06:02:34'); // 0.019722222222222 // Those methods are absolute by default but can return negative value // setting the second argument to false when start date is greater than end date echo Carbon::parse('12:01:23')->floatDiffInHours('06:02:34', false); // -5.9802777777778 echo Carbon::parse('2000-01-01 12:00')->floatDiffInDays('2000-02-11 06:00'); // 40.75 echo Carbon::parse('2000-01-01')->floatDiffInWeeks('2000-02-11'); // 5.8571428571429 echo Carbon::parse('2000-01-15')->floatDiffInMonths('2000-02-24'); // 1.3103448275862 // floatDiffInMonths count as many full months as possible from the start date // (for instance 31 days if the start is in January), then consider the number // of days in the months for ending chunks to reach the end date. // So the following result (ending with 24 march is different from previous one with 24 february): echo Carbon::parse('2000-02-15 12:00')->floatDiffInMonths('2000-03-24 06:00'); // 1.2822580645161 // floatDiffInYears apply the same logic (and so different results with leap years) echo Carbon::parse('2000-02-15 12:00')->floatDiffInYears('2010-03-24 06:00'); // 10.100684931507⚠️ Important note about the daylight saving times (DST), by default PHP DateTime does not take DST into account, that means for example that a day with only 23 hours like March the 30th 2014 in London will be counted as 24 hours long.$date = new DateTime('2014-03-30 00:00:00', new DateTimeZone('Europe/London')); // DST off echo $date->modify('+25 hours')->format('H:i'); // 01:00 (DST on, 24 hours only have been actually added)Carbon follow this behavior too for add/sub/diff seconds/minutes/hours. But we provide methods to works with real hours using timestamp:$date = new Carbon('2014-03-30 00:00:00', 'Europe/London'); // DST off echo $date->addRealHours(25)->format('H:i'); // 02:00 (DST on) echo $date->diffInRealHours('2014-03-30 00:00:00'); // 25 echo $date->diffInHours('2014-03-30 00:00:00'); // 26 echo $date->diffInRealMinutes('2014-03-30 00:00:00'); // 1500 echo $date->diffInMinutes('2014-03-30 00:00:00'); // 1560 echo $date->diffInRealSeconds('2014-03-30 00:00:00'); // 90000 echo $date->diffInSeconds('2014-03-30 00:00:00'); // 93600 echo $date->diffInRealMilliseconds('2014-03-30 00:00:00'); // 90000000 echo $date->diffInMilliseconds('2014-03-30 00:00:00'); // 93600000 echo $date->diffInRealMicroseconds('2014-03-30 00:00:00'); // 90000000000 echo $date->diffInMicroseconds('2014-03-30 00:00:00'); // 93600000000 echo $date->subRealHours(25)->format('H:i'); // 00:00 (DST off) // with float diff: $date = new Carbon('2019-10-27 00:00:00', 'Europe/Paris'); echo $date->floatDiffInRealHours('2019-10-28 12:30:00'); // 37.5 echo $date->floatDiffInHours('2019-10-28 12:30:00'); // 36.5 echo $date->floatDiffInRealMinutes('2019-10-28 12:00:30'); // 2220.5 echo $date->floatDiffInMinutes('2019-10-28 12:00:30'); // 2160.5 echo $date->floatDiffInRealSeconds('2019-10-28 12:00:00.5'); // 133200.5 echo $date->floatDiffInSeconds('2019-10-28 12:00:00.5'); // 129600.5 // above day unit, "real" will affect the decimal part based on hours and smaller units echo $date->floatDiffInRealDays('2019-10-28 12:30:00'); // 1.5625 echo $date->floatDiffInDays('2019-10-28 12:30:00'); // 1.5208333333333 echo $date->floatDiffInRealWeeks('2019-10-28 12:30:00'); // 0.22321428571429 echo $date->floatDiffInWeeks('2019-10-28 12:30:00'); // 0.2172619047619 echo $date->floatDiffInRealMonths('2019-10-28 12:30:00'); // 0.050403225806452 echo $date->floatDiffInMonths('2019-10-28 12:30:00'); // 0.049059139784946 echo $date->floatDiffInRealYears('2019-10-28 12:30:00'); // 0.0042808219178082 echo $date->floatDiffInYears('2019-10-28 12:30:00'); // 0.0041666666666667The same way you can use addRealX() and subRealX() on any unit.There are also special filter functions diffInDaysFiltered(), diffInHoursFiltered() and diffFiltered(), to help you filter the difference by days, hours or a custom interval. For example to count the weekend days between two instances:$dt = Carbon::create(2014, 1, 1); $dt2 = Carbon::create(2014, 12, 31); $daysForExtraCoding = $dt->diffInDaysFiltered(function(Carbon $date) { return $date->isWeekend(); }, $dt2); echo $daysForExtraCoding; // 104 $dt = Carbon::create(2014, 1, 1)->endOfDay(); $dt2 = $dt->copy()->startOfDay(); $littleHandRotations = $dt->diffFiltered(CarbonInterval::minute(), function(Carbon $date) { return $date->minute === 0; }, $dt2, true); // true as last parameter returns absolute value echo $littleHandRotations; // 24 $date = Carbon::now()->addSeconds(3666); echo $date->diffInSeconds(); // 3665 echo $date->diffInMinutes(); // 61 echo $date->diffInHours(); // 1 echo $date->diffInDays(); // 0 $date = Carbon::create(2016, 1, 5, 22, 40, 32); echo $date->secondsSinceMidnight(); // 81632 echo $date->secondsUntilEndOfDay(); // 4767 $date1 = Carbon::createMidnightDate(2016, 1, 5); $date2 = Carbon::createMidnightDate(2017, 3, 15); echo $date1->diffInDays($date2); // 435 echo $date1->diffInWeekdays($date2); // 311 echo $date1->diffInWeekendDays($date2); // 124 echo $date1->diffInWeeks($date2); // 62 echo $date1->diffInMonths($date2); // 14 echo $date1->diffInQuarters($date2); // 4 echo $date1->diffInYears($date2); // 1All diffIn*Filtered method take 1 callable filter as required parameter and a date object as optional second parameter, if missing, now is used. You may also pass true as third parameter to get absolute values.For advanced handle of the week/weekend days, use the following tools:echo implode(', ', Carbon::getDays()); // Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday $saturday = new Carbon('first saturday of 2019'); $sunday = new Carbon('first sunday of 2019'); $monday = new Carbon('first monday of 2019'); echo implode(', ', Carbon::getWeekendDays()); // 6, 0 var_dump($saturday->isWeekend()); // bool(true) var_dump($sunday->isWeekend()); // bool(true) var_dump($monday->isWeekend()); // bool(false) Carbon::setWeekendDays([ Carbon::SUNDAY, Carbon::MONDAY, ]); echo implode(', ', Carbon::getWeekendDays()); // 0, 1 var_dump($saturday->isWeekend()); // bool(false) var_dump($sunday->isWeekend()); // bool(true) var_dump($monday->isWeekend()); // bool(true) Carbon::setWeekendDays([ Carbon::SATURDAY, Carbon::SUNDAY, ]); // weekend days and start/end of week or not linked Carbon::setWeekStartsAt(Carbon::FRIDAY); Carbon::setWeekEndsAt(Carbon::WEDNESDAY); // and it does not need neither to precede the start var_dump(Carbon::getWeekStartsAt() === Carbon::FRIDAY); // bool(true) var_dump(Carbon::getWeekEndsAt() === Carbon::WEDNESDAY); // bool(true) echo $saturday->copy()->startOfWeek()->toRfc850String(); // Friday, 31-Mar-23 00:00:00 UTC echo $saturday->copy()->endOfWeek()->toRfc850String(); // Wednesday, 05-Apr-23 23:59:59 UTC // Be very careful with those global setters, remember, some other // code or third-party library in your app may expect initial weekend // days to work properly. Carbon::setWeekStartsAt(Carbon::MONDAY); Carbon::setWeekEndsAt(Carbon::SUNDAY); echo $saturday->copy()->startOfWeek()->toRfc850String(); // Monday, 27-Mar-23 00:00:00 UTC echo $saturday->copy()->endOfWeek()->toRfc850String(); // Sunday, 02-Apr-23 23:59:59 UTCDifference for HumansIt is easier for humans to read 1 month ago compared to 30 days ago. This is a common function seen in most date libraries so I thought I would add it here as well. The lone argument for the function is the other Carbon instance to diff against, and of course it defaults to now() if not specified.This method will add a phrase after the difference value relative to the instance and the passed in instance. There are 4 possibilities:When comparing a value in the past to default now:1 hour ago5 months agoWhen comparing a value in the future to default now:1 hour from now5 months from nowWhen comparing a value in the past to another value:1 hour before5 months beforeWhen comparing a value in the future to another value:1 hour after5 months afterYou may also pass CarbonInterface::DIFF_ABSOLUTE as a 2nd parameter to remove the modifiers ago, from now, etc : diffForHumans($other, CarbonInterface::DIFF_ABSOLUTE), CarbonInterface::DIFF_RELATIVE_TO_NOW to get modifiers ago or from now, CarbonInterface::DIFF_RELATIVE_TO_OTHER to get the modifiers before or after or CarbonInterface::DIFF_RELATIVE_AUTO (default mode) to get the modifiers either ago/from now if the 2 second argument is null or before/after if not.You may pass true as a 3rd parameter to use short syntax if available in the locale used : diffForHumans($other, CarbonInterface::DIFF_RELATIVE_AUTO, true).You may pass a number between 1 and 6 as a 4th parameter to get the difference in multiple parts (more precise diff) : diffForHumans($other, CarbonInterface::DIFF_RELATIVE_AUTO, false, 4).The $other instance can be a DateTime, a Carbon instance or any object that implement DateTimeInterface, if a string is passed it will be parsed to get a Carbon instance and if null is passed, Carbon::now() will be used instead.To avoid having too much argument and mix the order, you can use the verbose methods:shortAbsoluteDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)longAbsoluteDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)shortRelativeDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)longRelativeDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)shortRelativeToNowDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)longRelativeToNowDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)shortRelativeToOtherDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)longRelativeToOtherDiffForHumans(DateTimeInterface | null $other = null, int $parts = 1)PS: $other and $parts arguments can be swapped as need.// The most typical usage is for comments // The instance is the date the comment was created and its being compared to default now() echo Carbon::now()->subDays(5)->diffForHumans(); // 5 days ago echo Carbon::now()->diffForHumans(Carbon::now()->subYear()); // 11 months after $dt = Carbon::createFromDate(2011, 8, 1); echo $dt->diffForHumans($dt->copy()->addMonth()); // 1 month before echo $dt->diffForHumans($dt->copy()->subMonth()); // 1 month after echo Carbon::now()->addSeconds(5)->diffForHumans(); // 4 seconds from now echo Carbon::now()->subDays(24)->diffForHumans(); // 3 weeks ago echo Carbon::now()->subDays(24)->longAbsoluteDiffForHumans(); // 3 weeks echo Carbon::parse('2019-08-03')->diffForHumans('2019-08-13'); // 1 week before echo Carbon::parse('2000-01-01 00:50:32')->diffForHumans('@946684800'); // 50 minutes after echo Carbon::create(2018, 2, 26, 4, 29, 43)->longRelativeDiffForHumans(Carbon::create(2016, 6, 21, 0, 0, 0), 6); // 1 year 8 months 5 days 4 hours 29 minutes 43 seconds afterYou can also change the locale of the string using $date->locale('fr') before the diffForHumans() call. See the localization section for more detail.Since 2.9.0 diffForHumans() parameters can be passed as an array:If the argument is omitted or set to null, only Carbon::NO_ZERO_DIFF is enabled. Available options are:Carbon::ROUND/Carbon::CEIL/Carbon::FLOOR(none by default): only one of the 3 can be used at a time (other are ignored) and it requires'parts'to be set. By default, once the diff has as parts as'parts'setting requested and omit all remaining units.If Carbon::ROUND is enabled, the remaining units are summed and if they are >= 0.5 of the last unit of the diff, this unit will be rounded to the upper value.If Carbon::CEIL is enabled, the remaining units are summed and if they are > 0 of the last unit of the diff, this unit will be rounded to the upper value.If Carbon::FLOOR is enabled, the last diff unit is rounded down. It makes no difference from the default behavior for diffForHumans() as the interval can't have overflow, but this option may be needed when used with CarbonInterval::forHumans() (and unchecked intervals that may have 60 minutes or more, 24 hours or more, etc.). For example: CarbonInterval::make('1 hour and 67 minutes')->forHumans(['parts' => 1]) returns "1 hour" while CarbonInterval::make('1 hour and 67 minutes')->forHumans(['parts' => 1, 'options' => Carbon::FLOOR]) returns "2 hours".Carbon::NO_ZERO_DIFF (enabled by default): turns empty diff into 1 secondCarbon::JUST_NOW disabled by default): turns diff from now to now into "just now"Carbon::ONE_DAY_WORDS (disabled by default): turns "1 day from now/ago" to "yesterday/tomorrow"Carbon::TWO_DAY_WORDS (disabled by default): turns "2 days from now/ago" to "before yesterday/afterCarbon::SEQUENTIAL_PARTS_ONLY (disabled by default): will keep only the first sequence of units of the interval, for example if the diff would have been "2 weeks 1 day 34 minutes 12 seconds" as day and minute are not consecutive units, you will get: "2 weeks 1 day".Use the pipe operator to enable/disable multiple option at once, example: Carbon::ONE_DAY_WORDS | Carbon::TWO_DAY_WORDSYou also can use Carbon::enableHumanDiffOption($option), Carbon::disableHumanDiffOption($option), Carbon::setHumanDiffOptions($options) to change the default options and Carbon::getHumanDiffOptions() to get default options but you should avoid using it as being static it may conflict with calls from other code parts/third-party libraries.Aliases and reverse methods are provided for semantic purpose:from($other = null, $syntax = null, $short = false, $parts = 1, $options = null) (alias of diffForHumans)since($other = null, $syntax = null, $short = false, $parts = 1, $options = null) (alias of diffForHumans)to($other = null, $syntax = null, $short = false, $parts = 1, $options = null) (inverse result, swap before and future diff)until($other = null, $syntax = null, $short = false, $parts = 1, $options = null) (alias of to)fromNow($syntax = null, $short = false, $parts = 1, $options = null) (alias of from with first argument omitted unless the first argument is a DateTimeInterface, now used instead), for semantic usage: produce an "3 hours from now"-like string with dates in the futureago($syntax = null, $short = false, $parts = 1, $options = null) (alias of fromNow), for semantic usage: produce an "3 hours ago"-like string with dates in the pasttoNow($syntax = null, $short = false, $parts = 1, $options = null) (alias of to with first argument omitted, now used instead)timespan($other = null, $timezone = null) calls diffForHumans with options join = ', ' (coma-separated), syntax = CarbonInterface::DIFF_ABSOLUTE (no "ago"/"from now"/"before"/"after" wording), options = CarbonInterface::NO_ZERO_DIFF (no "just now"/"yesterday"/"tomorrow" wording), parts = -1 (no limits) In this mode, you can't change options but you can pass an optional date to compare with or a string + timezone to parse to get this date.ModifiersThese group of methods perform helpful modifications to the current instance. Most of them are self explanatory from their names... or at least should be. You'll also notice that the startOfXXX(), next() and previous() methods set the time to 00:00:00 and the endOfXXX() methods set the time to 23:59:59 for unit bigger than days.The only one slightly different is the average() function. It moves your instance to the middle date between itself and the provided Carbon argument.The powerful native modify() method of DateTime is available untouched. But we also provide an enhanced version of it: change() that allows some additional syntax like "next 3pm" and that is called internally by ->next() and ->previous().$dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->startOfSecond()->format('s.u'); // 45.000000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->endOfSecond()->format('s.u'); // 45.999999 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->startOf('second')->format('s.u'); // 45.000000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->endOf('second')->format('s.u'); // 45.999999 // ->startOf() and ->endOf() are dynamic equivalents to those methods $dt = Carbon::create(2012, 1, 31, 15, 32, 45); echo $dt->startOfMinute(); // 2012-01-31 15:32:00 $dt = Carbon::create(2012, 1, 31, 15, 32, 45); echo $dt->endOfMinute(); // 2012-01-31 15:32:59 $dt = Carbon::create(2012, 1, 31, 15, 32, 45); echo $dt->startOfHour(); // 2012-01-31 15:00:00 $dt = Carbon::create(2012, 1, 31, 15, 32, 45); echo $dt->endOfHour(); // 2012-01-31 15:59:59 $dt = Carbon::create(2012, 1, 31, 15, 32, 45); echo Carbon::getMidDayAt(); // 12 echo $dt->midDay(); // 2012-01-31 12:00:00 Carbon::setMidDayAt(13); echo Carbon::getMidDayAt(); // 13 echo $dt->midDay(); // 2012-01-31 13:00:00 Carbon::setMidDayAt(12); $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfDay(); // 2012-01-31 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfDay(); // 2012-01-31 23:59:59 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfMonth(); // 2012-01-01 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfMonth(); // 2012-01-31 23:59:59 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfYear(); // 2012-01-01 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfYear(); // 2012-12-31 23:59:59 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfDecade(); // 2010-01-01 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfDecade(); // 2019-12-31 23:59:59 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfCentury(); // 2001-01-01 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfCentury(); // 2100-12-31 23:59:59 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->startOfWeek(); // 2012-01-30 00:00:00 var_dump($dt->dayOfWeek == Carbon::MONDAY); // bool(true) : ISO8601 week starts on Monday $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->endOfWeek(); // 2012-02-05 23:59:59 var_dump($dt->dayOfWeek == Carbon::SUNDAY); // bool(true) : ISO8601 week ends on Sunday $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->next(Carbon::WEDNESDAY); // 2012-02-01 00:00:00 var_dump($dt->dayOfWeek == Carbon::WEDNESDAY); // bool(true) echo $dt->next('Wednesday'); // 2012-02-08 00:00:00 echo $dt->next('04:00'); // 2012-02-08 04:00:00 echo $dt->next('12:00'); // 2012-02-08 12:00:00 echo $dt->next('04:00'); // 2012-02-09 04:00:00 $dt = Carbon::create(2012, 1, 1, 12, 0, 0); echo $dt->next(); // 2012-01-08 00:00:00 $dt = Carbon::create(2012, 1, 31, 12, 0, 0); echo $dt->previous(Carbon::WEDNESDAY); // 2012-01-25 00:00:00 var_dump($dt->dayOfWeek == Carbon::WEDNESDAY); // bool(true) $dt = Carbon::create(2012, 1, 1, 12, 0, 0); echo $dt->previous(); // 2011-12-25 00:00:00 $start = Carbon::create(2014, 1, 1, 0, 0, 0); $end = Carbon::create(2014, 1, 30, 0, 0, 0); echo $start->average($end); // 2014-01-15 12:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfMonth(); // 2014-05-01 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfMonth(Carbon::MONDAY); // 2014-05-05 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfMonth(); // 2014-05-31 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfMonth(Carbon::TUESDAY); // 2014-05-27 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfMonth(2, Carbon::SATURDAY); // 2014-05-10 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfQuarter(); // 2014-04-01 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfQuarter(Carbon::MONDAY); // 2014-04-07 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfQuarter(); // 2014-06-30 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfQuarter(Carbon::TUESDAY); // 2014-06-24 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfQuarter(2, Carbon::SATURDAY); // 2014-04-12 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->startOfQuarter(); // 2014-04-01 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->endOfQuarter(); // 2014-06-30 23:59:59 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfYear(); // 2014-01-01 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfYear(Carbon::MONDAY); // 2014-01-06 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfYear(); // 2014-12-31 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfYear(Carbon::TUESDAY); // 2014-12-30 00:00:00 echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfYear(2, Carbon::SATURDAY); // 2014-01-11 00:00:00 echo Carbon::create(2018, 2, 23, 0, 0, 0)->nextWeekday(); // 2018-02-26 00:00:00 echo Carbon::create(2018, 2, 23, 0, 0, 0)->previousWeekday(); // 2018-02-22 00:00:00 echo Carbon::create(2018, 2, 21, 0, 0, 0)->nextWeekendDay(); // 2018-02-24 00:00:00 echo Carbon::create(2018, 2, 21, 0, 0, 0)->previousWeekendDay(); // 2018-02-18 00:00:00sRounding is also available for any unit:$dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->roundMillisecond()->format('H:i:s.u'); // 15:32:45.654000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->roundSecond()->format('H:i:s.u'); // 15:32:46.000000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->floorSecond()->format('H:i:s.u'); // 15:32:45.000000 $dt = new Carbon('2012-01-31 15:32:15'); echo $dt->roundMinute()->format('H:i:s'); // 15:32:00 $dt = new Carbon('2012-01-31 15:32:15'); echo $dt->ceilMinute()->format('H:i:s'); // 15:33:00 // and so on up to millennia! // precision rounding can be set, example: rounding to ten minutes $dt = new Carbon('2012-01-31 15:32:15'); echo $dt->roundMinute(10)->format('H:i:s'); // 15:30:00 // and round, floor and ceil methods are shortcut for second rounding: $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->round()->format('H:i:s.u'); // 15:32:46.000000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->floor()->format('H:i:s.u'); // 15:32:45.000000 $dt = new Carbon('2012-01-31 15:32:45.654321'); echo $dt->ceil()->format('H:i:s.u'); // 15:32:46.000000 // you can also pass the unit dynamically (and still precision as second argument): $dt = new Carbon('2012-01-31'); echo $dt->roundUnit('month', 2)->format('Y-m-d'); // 2012-01-01 $dt = new Carbon('2012-01-31'); echo $dt->floorUnit('month')->format('Y-m-d'); // 2012-01-01 $dt = new Carbon('2012-01-31'); echo $dt->ceilUnit('month', 4)->format('Y-m-d'); // 2012-05-01ConstantsThe following constants are defined in the Carbon class.// These getters specifically return integers, ie intval() var_dump(Carbon::SUNDAY); // int(0) var_dump(Carbon::MONDAY); // int(1) var_dump(Carbon::TUESDAY); // int(2) var_dump(Carbon::WEDNESDAY); // int(3) var_dump(Carbon::THURSDAY); // int(4) var_dump(Carbon::FRIDAY); // int(5) var_dump(Carbon::SATURDAY); // int(6) var_dump(Carbon::YEARS_PER_CENTURY); // int(100) var_dump(Carbon::YEARS_PER_DECADE); // int(10) var_dump(Carbon::MONTHS_PER_YEAR); // int(12) var_dump(Carbon::WEEKS_PER_YEAR); // int(52) var_dump(Carbon::DAYS_PER_WEEK); // int(7) var_dump(Carbon::HOURS_PER_DAY); // int(24) var_dump(Carbon::MINUTES_PER_HOUR); // int(60) var_dump(Carbon::SECONDS_PER_MINUTE); // int(60)$dt = Carbon::createFromDate(2012, 10, 6); if ($dt->dayOfWeek === Carbon::SATURDAY) { echo 'Place bets on Ottawa Senators Winning!'; }SerializationThe Carbon instances can be serialized (including CarbonImmutable, CarbonInterval and CarbonPeriod).$dt = Carbon::create(2012, 12, 25, 20, 30, 00, 'Europe/Moscow'); echo serialize($dt); // O:13:"Carbon\Carbon":3:{s:4:"date";s:26:"2012-12-25 20:30:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/Moscow";} // same as: echo $dt->serialize(); // O:13:"Carbon\Carbon":3:{s:4:"date";s:26:"2012-12-25 20:30:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/Moscow";} $dt = 'O:13:"Carbon\Carbon":3:{s:4:"date";s:26:"2012-12-25 20:30:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:13:"Europe/Moscow";}'; echo unserialize($dt)->format('Y-m-d\TH:i:s.uP T'); // 2012-12-25T20:30:00.000000+04:00 MSK // same as: echo Carbon::fromSerialized($dt)->format('Y-m-d\TH:i:s.uP T'); // 2012-12-25T20:30:00.000000+04:00 MSKJSONThe Carbon instances can be encoded to and decoded from JSON. Since the version 2.4, we explicitly require the PHP JSON extension. It should have no impact as this extension is bundled by default with PHP. If the extension is disabled, be aware you will be locked on 2.3. But you still can use --ignore-platform-reqs on composer update/install to upgrade then polyfill the missing JsonSerializable interface by including JsonSerializable.php.$dt = Carbon::create(2012, 12, 25, 20, 30, 00, 'Europe/Moscow'); echo json_encode($dt); // "2012-12-25T16:30:00.000000Z" $json = '{"date":"2012-12-25 20:30:00.000000","timezone_type":3,"timezone":"Europe\/Moscow"}'; $dt = Carbon::__set_state(json_decode($json, true)); echo $dt->format('Y-m-d\TH:i:s.uP T'); // 2012-12-25T20:30:00.000000+04:00 MSKYou can use settings(['toJsonFormat' => $format]) to customize the serialization.$dt = Carbon::create(2012, 12, 25, 20, 30, 00, 'Europe/Moscow')->settings([ 'toJsonFormat' => function ($date) { return $date->getTimestamp(); }, ]); echo json_encode($dt); // 1356453000If you want to apply this globally, first consider using factory, else or if you use Carbon 1 you can use:$dt = Carbon::create(2012, 12, 25, 20, 30, 00, 'Europe/Moscow'); Carbon::serializeUsing(function ($date) { return $date->valueOf(); }); echo json_encode($dt); // 1356453000000 // Call serializeUsing with null to reset the serializer: Carbon::serializeUsing(null);未完待续...
use Carbon\Carbon; // Carbon 类在 Carbon 命名空间中声明 // 获取当前时间 echo Carbon::now(); // 2017-04-07 16:32:28 // 今天 echo Carbon::today(); // 2017-04-07 00:00:00 // 明天 echo Carbon::tomorrow(); // 2017-04-08 00:00:00 // 昨天 echo Carbon::yesterday(); // 2017-04-06 00:00:00 // 获取前一天的开始时间 echo Carbon::now()->yesterday()->startOfDay(); // 2017-04-06 00:00:00 // 获取前一天的结束时间 echo Carbon::now()->yesterday()->endOfDay(); // 2017-04-06 23:59:59 //上一周开始时间 (星期一) echo Carbon::now()->previous()->startOfWeek(); // 2017-03-27 00:00:00 // 这周周一 echo Carbon::now()->startOfWeek(); // 2017-04-03 00:00:00 //上一周结束时间 (星期天) echo Carbon::now()->previous()->endOfWeek(); // 2017-04-02 23:59:59 // 这周周天 echo Carbon::now()->endOfWeek(); // 2017-04-09 23:59:59 //获取上一月的开始时间 echo Carbon::now()->subMonth(1)->startOfMonth(); // 2017-03-01 00:00:00 // 获取上一月的结束时间 echo Carbon::now()->subMonth(1)->endOfMonth(); // 2017-03-31 23:59:59 // 这个月的第一天开始时间 echo Carbon::now()->startOfMonth(); // 2017-04-01 00:00:00 // 这个月的最后一天结束时间 echo Carbon::now()->endOfMonth(); // 2017-04-30 23:59:59 // 获取上一年的开始时间 echo Carbon::now()->subYear(1)->startOfYear(); // 2016-01-01 00:00:00 // 今年开始时间 echo Carbon::now()->startOfYear(); // 2017-01-01 00:00:00 echo Carbon::now()->lastOfYear()->startOfYear(); // 2017-01-01 00:00:00 // 获取上一年的结束时间 echo Carbon::now()->subYear(1)->endOfYear(); // 2016-12-31 23:59:59 // 今年结束时间 echo Carbon::now()->endOfYear(); // 2017-12-31 23:59:59 echo Carbon::now()->lastOfYear()->endOfYear(); // 2017-12-31 23:59:59 // 获取当前时间的固定格式 echo Carbon::now()->format('Y-m-d'); // 2017-04-07 // 几号 echo Carbon::now()->day; // 7 // 几月 echo Carbon::now()->month; // 4 // 年 echo Carbon::now()->year; // 2017 // 小时 echo Carbon::now()->hour; // 分钟 echo Carbon::now()->minute; // 上周的今天是星期几 echo Carbon::now()->dayOfWeek; // 5 // 今天是365天中的第几天 echo Carbon::now()->dayOfYear; // 96 // 这个月中的第几周 echo Carbon::now()->weekOfMonth; // 1 // 年中的第几周 echo Carbon::now()->weekOfYear; // 14 // 季度 echo Carbon::now()->quarter; // 2 // 几岁 echo Carbon::createFromDate(1991, 5, 21)->age; // 25 // 这个月有几天 echo Carbon::now()->daysInMonth; // 30 var_dump(isset(Carbon::now()->hour)); // bool(true) var_dump(empty(Carbon::now()->year)); // bool(false) echo Carbon::now()->year(2017)->month(5)->day(21)->hour(22)->minute(32)->second(5)->toDateTimeString(); // 2017-05-21 22:32:05 echo Carbon::now()->setDate(2017, 5, 21)->setTime(22, 32, 5)->toDateTimeString(); // 2017-05-21 22:32:05 echo Carbon::now()->setDateTime(2017, 5, 21, 22, 32, 5)->toDateTimeString(); // 2017-05-21 22:32:05 // 日期解析 echo new Carbon('now'); echo Carbon::parse('now'); // 2017-04-07 17:54:35 echo Carbon::parse('today'); // 2017-04-07 00:00:00 echo Carbon::parse('yesterday'); // 2017-04-06 00:00:00 echo Carbon::parse('2 days ago'); // 2017-04-05 17:56:28 echo Carbon::parse('+3 days'); // 2017-04-10 17:57:14 echo Carbon::parse('-3 days'); // 2017-04-04 17:57:37 echo Carbon::parse('+2 weeks'); // 2017-04-21 17:58:05 echo Carbon::parse('+4 months'); // 2017-08-07 17:58:32 echo Carbon::parse('-1 year'); // 2016-04-07 17:58:56 echo Carbon::parse('next wednesday'); // 2017-04-12 00:00:00 echo Carbon::parse('last friday'); // 2017-03-31 00:00:00 // 将carbon对象转换成string类型 echo Carbon::createFromTimestamp(-1)->toDateTimeString(); // 1970-01-01 07:59:59 echo Carbon::now()->toDateString(); // 2017-04-07 echo Carbon::now()->toDateTimeString(); // 2017-04-07 16:53:28 echo Carbon::now()->toFormattedDateString(); // Apr 7, 2017 echo Carbon::now()->toTimeString(); // 18:04:00 echo Carbon::now()->toDayDateTimeString(); // Fri, Apr 7, 2017 6:04 PM // 获取当前时间的时间戳 echo Carbon::now()->timestamp; // 1491554091 echo Carbon::now()->timestamp(1491554091)->toDateTimeString(); // 2017-04-07 16:34:51 // 设置当前地区的时区 echo Carbon::now()->timezone('Asia/Shanghai'); // 2017-04-07 16:35:35 // 直接使用字符串 echo Carbon::now('Europe/London'); // 2017-04-07 09:36:41 // createFromDate()将默认的时间到现在。 createFromTime()将日期默认为今天。 echo Carbon::createFromDate(2018, 1, 1, 'Europe/London'); // 2018-01-01 16:39:40 echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22')->toDateTimeString(); // 1975-05-21 22:00:00 echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22'); // 1975-05-21 22:00:00 // create()将默认任何null参数到当前相应的值 echo Carbon::create(2000, 1, 1, 0, 0, 0); // 2000-01-01 00:00:00 // 日期比较 echo Carbon::now()->tzName; // PRC $first = Carbon::create(2017, 4, 10, 11, 26, 30); $second = Carbon::create(2017, 4, 10, 11, 26, 30, 'Asia/Shanghai'); echo $first->toDateTimeString(); // 2017-04-10 11:26:30 echo $first->tzName; // PRC echo $second->toDateTimeString(); // 2017-04-10 11:26:30 echo $second->tzName; // Asia/Shanghai // 判断两个日期是否相等 var_dump($first->eq($second)); // bool(true) // 判断第一个日期是否不等于第二个日期 var_dump($first->ne($second)); // bool(false) // 判断第一个日期是否比第二个日期大 var_dump($first->gt($second)); // bool(false) // 判断第一个日期是否大于等于第二个日期 var_dump($first->gte($second)); // bool(true) // 判断第一个日期是否比第二个日期小 var_dump($first->lt($second)); // bool(false) // 判断第一个日期是否小于等于第二个日期 var_dump($first->lte($second)); // bool(true) // 设置日期和时间 $first->setDateTime(2017, 1, 1, 0, 0, 0); $second->setDateTime(2017, 1, 1, 0, 0, 0); var_dump($first->eq($second)); // bool(true) var_dump($first->ne($second)); // bool(false) var_dump($first->gt($second)); // bool(false) var_dump($first->gte($second)); // bool(true) var_dump($first->lt($second)); // bool(false) var_dump($first->lte($second)); // bool(true) // 要判断一个日期是否介于两个日期之间，可以使用 between() 方法，第三个可选参数指定比较是否可以相等，默认为 true $first = Carbon::create(2012, 9, 5, 1); $second = Carbon::create(2012, 9, 5, 5); var_dump(Carbon::create(2012, 9, 5, 3)->between($first, $second)); // bool(true) var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second)); // bool(true) var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second, false)); // bool(false) $dt1 = Carbon::create(2012, 1, 1, 0, 0, 0); $dt2 = Carbon::create(2014, 1, 30, 0, 0, 0); // 返回最小日期 echo $dt1->min($dt2); // 2012-01-01 00:00:00 $dt1 = Carbon::create(2012, 1, 1, 0, 0, 0); $dt2 = Carbon::create(2014, 1, 30, 0, 0, 0); // 返回最大日期 echo $dt1->max($dt2); // 2014-01-30 00:00:00 // now is the default param $dt1 = Carbon::create(2000, 1, 1, 0, 0, 0); echo $dt1->max(); // 2017-04-10 11:51:23 $dt = Carbon::now(); // 确定实例是一个工作日 $dt->isWeekday(); // 确定实例是周末的一天 $dt->isWeekend(); $dt->isYesterday(); $dt->isToday(); $dt->isTomorrow(); // 是否比现在的时间大 $dt->isFuture(); // 是否比现在的时间小 $dt->isPast(); // 确定实例是闰年 $dt->isLeapYear(); // 检查传入日期是同一天的当前实例 $dt->isSameDay(Carbon::now()); $born = Carbon::createFromDate(1987, 4, 23); $noCake = Carbon::createFromDate(2014, 9, 26); $yesCake = Carbon::createFromDate(2014, 4, 23); $overTheHill = Carbon::now()->subYears(50); // 检查它的生日。比较两个日期的日期 var_dump($born->isBirthday($noCake)); // bool(false) var_dump($born->isBirthday($yesCake)); // bool(true) var_dump($overTheHill->isBirthday()); // bool(true) -> default compare it to today! // 日期操作 // add（增加）, sub（减去） $dt = Carbon::create(2017, 4, 10, 0); echo $dt->toDateTimeString(); // 2017-04-10 00:00:00 echo $dt->addYears(5); // 2022-04-10 00:00:00 echo $dt->addYear(); // 2023-04-10 00:00:00 echo $dt->subYear(); // 2022-04-10 00:00:00 echo $dt->subYears(5); // 2017-04-10 00:00:00 echo $dt->addMonths(6); // 2017-10-10 00:00:00 echo $dt->addMonth(); // 2017-11-10 00:00:00 equivalent of $dt->month($dt->month + 1); so it wraps echo $dt->subMonth(); // 2017-10-10 00:00:00 echo $dt->subMonths(6); // 2017-04-10 00:00:00 echo $dt->addDays(5); // 2017-04-15 00:00:00 echo $dt->addDay(); // 2017-04-16 00:00:00 echo $dt->subDay(); // 2017-04-15 00:00:00 echo $dt->subDays(5); // 2017-04-10 00:00:00 echo $dt->addWeekdays(4); // 2017-04-14 00:00:00 echo $dt->addWeekday(); // 2017-04-17 00:00:00 echo $dt->subWeekday(); // 2017-04-14 00:00:00 echo $dt->subWeekdays(4); // 2017-04-10 00:00:00 echo $dt->addWeeks(1); // 2017-04-17 00:00:00 echo $dt->addWeek(); // 2017-04-24 00:00:00 echo $dt->subWeek(); // 2017-04-17 00:00:00 echo $dt->subWeeks(1); // 2017-04-10 00:00:00 echo $dt->addHours(24); // 2017-04-11 00:00:00 echo $dt->addHour(); // 2017-04-11 01:00:00 echo $dt->subHour(); // 2017-04-11 00:00:00 echo $dt->subHours(24); // 2017-04-10 00:00:00 echo $dt->addMinutes(61); // 2017-04-10 01:01:00 echo $dt->addMinute(); // 2017-04-10 01:02:00 echo $dt->subMinute(); // 2017-04-10 01:01:00 echo $dt->subMinutes(61); // 2017-04-10 00:00:00 echo $dt->addSeconds(61); // 2017-04-10 00:01:01 echo $dt->addSecond(); // 2017-04-10 00:01:02 echo $dt->subSecond(); // 2017-04-10 00:01:01 echo $dt->subSeconds(61); // 2017-04-10 00:00:00 // modify 方法，参数格式为 + 或 - 跟上值及单位 echo Carbon::now()->modify('+15 days'); // 2017-04-25 12:26:02 echo Carbon::now()->modify('-2 days'); // 2017-04-08 12:26:02 echo Carbon::now()->modify('-2 day'); // 2017-04-08 12:28:31 echo Carbon::now()->modify('-2 weekday'); // 2017-04-06 00:00:00 echo Carbon::now()->modify('-2 month'); // 2017-02-10 12:29:36 echo Carbon::now()->modify('-2 year'); // 2015-04-10 12:31:13 echo Carbon::now()->modify('-2 week'); // 2017-03-27 12:31:13 echo Carbon::now()->modify('-2 hour'); // 2017-04-10 10:31:13 echo Carbon::now()->modify('-2 minute'); // 2017-04-10 12:29:13 echo Carbon::now()->modify('-2 second'); // 2017-04-10 12:31:11 echo Carbon::now()->subDays(5)->diffForHumans(); // 5天前 echo Carbon::now()->diffForHumans(Carbon::now()->subYear()); // 1年后 $dt = Carbon::createFromDate(2017, 4, 1); echo $dt->diffForHumans($dt->copy()->addMonth()); // 1月前 echo $dt->diffForHumans($dt->copy()->subMonth()); // 1月后 echo Carbon::now()->addSeconds(5)->diffForHumans(); // 距现在5秒 echo Carbon::now()->subDays(24)->diffForHumans(); // 3周前 echo Carbon::now()->subDays(24)->diffForHumans(null, true); // 3周 $dt = Carbon::now(); // 年的差异 echo $dt->diffInYears($dt->copy()->addYear(2)); // 2 echo $dt->diffInMonths(); // 0 echo $dt->diffInMinutes(); // 0 //指定返回日期的格式 $now = Carbon::now();// 2020-03-14 15:18:34 $firstDay = $now->firstOfMonth()->format('Ymd');// 20200301 $lastDay = $now->lastOfMonth()->format('Ymd');// 20200331 //根据当地描述事件格式 $dt = Carbon::now("Asia/Shanghai"); echo $dt; setlocale(LC_TIME, 'Chinese'); var_dump($dt->localeDayOfWeek); setlocale(LC_TIME, '');
Laravel 8.x新增的AsArrayObject和AsCollection字段映射（casts）
背景： laravel原来可以把数据库中的JSON / TEXT字段转换为array或collection，类似这样：$casts = ['options' => 'array'];但是这个特性，带来很多便利的同时，也有一些不足之处，比如当只是更新array当中某个属性时，很多开发者倾向于这样写:$user = User::find(1); $user->options['foo'] = 'bar'; $user->save();貌似应该起作用的逻辑，在这里却不行，这个经过laravel cast转换出来的array，要更改其中的某个属性，必须对整个array进行操作才行，通常是覆写整个array：$user = User::find(1); $user->options = ['foo' => 'bar']; $user->save();为了解决这个可能误导很多新手的问题，在laravel 8的后期版本，开始引入了AsArrayObject + AsCollection这两个新的cast类型。AsArrayObject通过PHP的ArrayObject来实现，能够以array的常见方式来操作object：// model里定义cast... $casts = ['options' => AsArrayObject::class]; // 具体操作... $user = User::find(1); $user->options['foo']['bar'] = 'baz'; $user->save();需要注意的是，这个时候的ArrayObject ，不能放进常见的array函数里来操作，比如array_map, 这种情况下，你可以通过$user->options->toArray()来获取其背后的原始array，或者也可以通过$user->options->collect()来将其转换为collection实例。基于其新增的便利，所以以后我们再想着cast某个字段为array或者collection的时候，不妨默认cast为AsArrayObject或者AsCollection类型，以后的laravel文档也会重点展示这两个类型的使用。
Versioning SchemeSupport PolicyLaravel 10Versioning SchemeLaravel and its other first-party packages follow Semantic Versioning. Major framework releases are released every year (~Q1), while minor and patch releases may be released as often as every week. Minor and patch releases should never contain breaking changes.When referencing the Laravel framework or its components from your application or package, you should always use a version constraint such as ^10.0, since major releases of Laravel do include breaking changes. However, we strive to always ensure you may update to a new major release in one day or less.Named ArgumentsNamed arguments are not covered by Laravel's backwards compatibility guidelines. We may choose to rename function arguments when necessary in order to improve the Laravel codebase. Therefore, using named arguments when calling Laravel methods should be done cautiously and with the understanding that the parameter names may change in the future.Support PolicyFor all Laravel releases, bug fixes are provided for 18 months and security fixes are provided for 2 years. For all additional libraries, including Lumen, only the latest major release receives bug fixes. In addition, please review the database versions supported by Laravel.VersionPHP (*)ReleaseBug Fixes UntilSecurity Fixes Until87.3 - 8.1September 8th, 2020July 26th, 2022January 24th, 202398.0 - 8.2February 8th, 2022August 8th, 2023February 6th, 2024108.1 - 8.2February 14th, 2023August 6th, 2024February 4th, 2025118.2Q1 2024August 5th, 2025February 3rd, 2026End of lifeSecurity fixes only(*) Supported PHP versionsLaravel 10As you may know, Laravel transitioned to yearly releases with the release of Laravel 8. Previously, major versions were released every 6 months. This transition is intended to ease the maintenance burden on the community and challenge our development team to ship amazing, powerful new features without introducing breaking changes. Therefore, we have shipped a variety of robust features to Laravel 9 without breaking backwards compatibility.Therefore, this commitment to ship great new features during the current release will likely lead to future "major" releases being primarily used for "maintenance" tasks such as upgrading upstream dependencies, which can be seen in these release notes.Laravel 10 continues the improvements made in Laravel 9.x by introducing argument and return types to all application skeleton methods, as well as all stub files used to generate classes throughout the framework. In addition, a new, developer-friendly abstraction layer has been introduced for starting and interacting with external processes. Further, Laravel Pennant has been introduced to provide a wonderful approach to managing your application's "feature flags".PHP 8.1Laravel 10.x requires a minimum PHP version of 8.1.TypesApplication skeleton and stub type-hints were contributed by Nuno Maduro .On its initial release, Laravel utilized all of the type-hinting features available in PHP at the time. However, many new features have been added to PHP in the subsequent years, including additional primitive type-hints, return types, and union types.Laravel 10.x thoroughly updates the application skeleton and all stubs utilized by the framework to introduce argument and return types to all method signatures. In addition, extraneous "doc block" type-hint information has been deleted.This change is entirely backwards compatible with existing applications. Therefore, existing applications that do not have these type-hints will continue to function normally.Laravel PennantLaravel Pennant was developed by Tim MacDonald .A new first-party package, Laravel Pennant, has been released. Laravel Pennant offers a light-weight, streamlined approach to managing your application's feature flags. Out of the box, Pennant includes an in-memory array driver and a database driver for persistent feature storage.Features can be easily defined via the Feature::define method:use Laravel\Pennant\Feature;use Illuminate\Support\Lottery; Feature::define('new-onboarding-flow', function() {returnLottery::odds(1, 10);});Once a feature has been defined, you may easily determine if the current user has access to the given feature:if (Feature::active('new-onboarding-flow')) {// ...}Of course, for convenience, Blade directives are also available:@feature('new-onboarding-flow') @endfeaturePennant offers a variety of more advanced features and APIs. For more information, please consult the comprehensive Pennant documentation.Process InteractionThe process abstraction layer was contributed by Nuno Maduro and Taylor Otwell .Laravel 10.x introduces a beautiful abstraction layer for starting and interacting with external processes via a new Process facade:use Illuminate\Support\Facades\Process; $result=Process::run('ls -la'); return$result->output();Processes may even be started in pools, allowing for the convenient execution and management of concurrent processes:use Illuminate\Process\Pool;use Illuminate\Support\Facades\Process; [$first, $second, $third] =Process::concurrently(function(Pool$pool) {$pool->command('cat first.txt');$pool->command('cat second.txt');$pool->command('cat third.txt');}); return$first->output();In addition, processes may be faked for convenient testing:Process::fake(); // ... Process::assertRan('ls -la');For more information on interacting with processes, please consult the comprehensive process documentation.Test ProfilingTest profiling was contributed by Nuno Maduro .The Artisan test command has received a new --profile option that allows you to easily identify the slowest tests in your application:php artisantest--profileFor convenience, the slowest tests will be displayed directly within the CLI output:Pest ScaffoldingNew Laravel projects may now be created with Pest test scaffolding by default. To opt-in to this feature, provide the --pest flag when creating a new application via the Laravel installer:laravel newexample-application--pestGenerator CLI PromptsGenerator CLI prompts were contributed by Jess Archer .To improve the framework's developer experience, all of Laravel's built-in make commands no longer require any input. If the commands are invoked without input, you will be prompted for the required arguments:php artisanmake:controllerHorizon / Telescope FaceliftHorizon and Telescope have been updated with a fresh, modern look including improved typography, spacing, and design: