This repository contains some useful collection macros.
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.
You're free to use this package (it's MIT-licensed), but if it makes it to your production environment you are required to send us a postcard from your hometown, mentioning which of our package(s) you are using.
Our address is: Spatie, Samberstraat 69D, 2060 Antwerp, Belgium.
The best postcards will get published on the open source page on our website.
You can pull in the package via composer:
composer require spatie/laravel-collection-macrosThe package will automatically register itself.
afteratbeforechunkBycollecteachConsextractfilterMapfirstOrFailfromPairsglobgroupByModelifAnyifEmptynonepaginateparallelMappluckToArrayrotatesectionBysimplePaginatesliceBeforetailtoPairstransposevalidatewithSize
Get the next item from the collection.
$collection = collect([1,2,3]);
$currentItem = 2;
$currentItem = $collection->after($currentItem); // return 3;
$collection->after($currentItem); // return null;
$currentItem = $collection->after(function($item) {
return $item > 1;
}); // return 3;You can also pass a second parameter to be used as a fallback.
$collection = collect([1,2,3]);
$currentItem = 3;
$collection->after($currentItem, $collection->first()); // return 1;Retrieve an item at an index.
$data = new Collection([1, 2, 3]);
$data->at(0); // 1
$data->at(1); // 2
$data->at(-1); // 3Get the previous item from the collection.
$collection = collect([1,2,3]);
$currentItem = 2;
$currentItem = $collection->before($currentItem); // return 1;
$collection->before($currentItem); // return null;
$currentItem = $collection->before(function($item) {
return $item > 2;
}); // return 2;You can also pass a second parameter to be used as a fallback.
$collection = collect([1,2,3]);
$currentItem = 1;
$collection->before($currentItem, $collection->last()); // return 3;Chunks the values from a collection into groups as long the given callback is true. If the optional parameter $preserveKeys as true is passed, it will preserve the original keys.
collect(['A', 'A', 'B', 'A'])->chunkBy(function($item) {
return $item == 'A';
}); // return Collection([['A', 'A'],['B'], ['A']])Get an item at a given key, and collect it.
$collection = collect([
'foo' => [1, 2, 3],
'bar' => [4, 5, 6],
]);
$collection->collect('foo'); // Collection([1, 2, 3])You can also pass a second parameter to be used as a fallback.
$collection = collect([
'foo' => [1, 2, 3],
'bar' => [4, 5, 6],
]);
$collection->collect('baz', ['Nope']); // Collection(['Nope'])Get the following consecutive neighbours in a collection from a given chunk size. If the optional parameter $preserveKeys as true is passed, it will preserve the original keys.
collect([1, 2, 3, 4])->eachCons(2); // return collect([[1, 2], [2, 3], [3, 4]])Extract keys from a collection. This is very similar to only, with two key differences:
extractreturns an array of values, not an associative array- If a value doesn't exist, it will fill the value with
nullinstead of omitting it
extract is useful when using PHP 7.1 short list() syntax.
[$name, $role] = collect($user)->extract('name', 'role.name');Map a collection and remove falsy values in one go.
$collection = collect([1, 2, 3, 4, 5, 6])->filterMap(function ($number) {
$quotient = $number / 3;
return is_integer($quotient) ? $quotient : null;
});
$collection->toArray(); // returns [1, 2]Get the first item. Throws Spatie\CollectionMacros\Exceptions\CollectionItemNotFound if the item was not found.
$collection = collect([1, 2, 3, 4, 5, 6])->firstOrFail();
$collection->toArray(); // returns [1]
collect([])->firstOrFail(); // throws Spatie\CollectionMacros\Exceptions\CollectionItemNotFoundTransform a collection into an associative array form collection item.
$collection = collect(['a', 'b'], ['c', 'd'], ['e', 'f'])->fromPairs();
$collection->toArray(); // returns ['a' => 'b', 'c' => 'd', 'e' => 'f']Returns a collection of a glob() result.
Collection::glob('config/*.php');Similar to groupBy, but groups the collection by an Eloquent model. Since the key is an object instead of an integer or string, the results are divided into separate arrays.
$posts->groupByModel('category');
// [
// [$categoryA, [/*...$posts*/]],
// [$categoryB, [/*...$posts*/]],
// ];Full signature: groupByModel($callback, $preserveKeys, $modelKey, $itemsKey)
Executes the passed callable if the collection isn't empty. The entire collection will be returned.
collect()->ifAny(function(Collection $collection) { // empty collection so this won't get called
echo 'Hello';
});
collect([1, 2, 3])->ifAny(function(Collection $collection) { // non-empty collection so this will get called
echo 'Hello';
});Executes the passed callable if the collection is empty. The entire collection will be returned.
collect()->ifEmpty(function(Collection $collection) { // empty collection so this will called
echo 'Hello';
});
collect([1, 2, 3])->ifEmpty(function(Collection $collection) { // non-empty collection so this won't get called
echo 'Hello';
});Checks whether a collection doesn't contain any occurrences of a given item, key-value pair, or passing truth test. The function accepts the same parameters as the contains collection method.
collect(['foo'])->none('bar'); // returns true
collect(['foo'])->none('foo'); // returns false
collect([['name' => 'foo']])->none('name', 'bar'); // returns true
collect([['name' => 'foo']])->none('name', 'foo'); // returns false
collect(['name' => 'foo'])->none(function ($key, $value) {
return $key === 'name' && $value === 'bar';
}); // returns trueCreate a LengthAwarePaginator instance for the items in the collection.
collect($posts)->paginate(5);This paginates the contents of $posts with 5 items per page. paginate accepts quite some options, head over to the Laravel docs for an in-depth guide.
paginate(int $perPage = 15, string $pageName = 'page', int $page = null, int $total = null, array $options = [])
Identical to map but each item in the collection will be processed in parallel. Before using this macro you should pull in the amphp/parallel-functions package.
composer require amphp/parallel-functionsBe aware that under the hood some overhead is introduced to make the parallel processing possible. When your $callable is only a simple operation it's probably better to use map instead. Also keep in mind that parallelMap can be memory intensive.
$pageSources = collect($urls)->parallelMap(function($url) {
return file_get_contents($url);
});The page contents of the given $urls will be fetched at the same time. The underlying amp sets a maximum of 32 concurrent processes by default.
There is a second (optional) parameter, through which you can define a custom parallel processing pool. It looks like this:
use Amp\Parallel\Worker\DefaultPool;
$pool = new DefaultPool(8);
$pageSources = collect($urls)->parallelMap(function($url) {
return file_get_contents($url);
}, $pool);If you don't need to extend the worker pool, or can't be bothered creating the new pool yourself; you can use an integer the the number of workers you'd like to use. A new DefaultPool will be created for you:
$pageSources = collect($urls)->parallelMap(function($url) {
return file_get_contents($url);
}, 8);This helps to reduce the memory overhead, as the default worker pool limit is 32 (as defined in amphp/parallel). Using fewer worker threads can significantly reduce memory and processing overhead, in many cases. Benchmark and customise the worker thread limit to suit your particular use-case.
Returns array of values of a given key.
$collection = collect([
['a' => 1, 'b' => 10],
['a' => 2, 'b' => 20],
['a' => 3, 'b' => 30]
]);
$collection->pluckToArray('a'); // returns [1, 2, 3]Rotate the items in the collection with given offset
$collection = collect([1, 2, 3, 4, 5, 6]);
$rotate = $collection->rotate(1);
$rotate->toArray();
// [2, 3, 4, 5, 6, 1]Splits a collection into sections grouped by a given key. Similar to groupBy but respects the order of the items in the collection and reuses existing keys.
$collection = collect([
['name' => 'Lesson 1', 'module' => 'Basics'],
['name' => 'Lesson 2', 'module' => 'Basics'],
['name' => 'Lesson 3', 'module' => 'Advanced'],
['name' => 'Lesson 4', 'module' => 'Advanced'],
['name' => 'Lesson 5', 'module' => 'Basics'],
]);
$collection->sectionBy('module');
// [
// ['Basics', [
// ['name' => 'Lesson 1', 'module' => 'Basics'],
// ['name' => 'Lesson 2', 'module' => 'Basics'],
// ]],
// ['Advanced', [
// ['name' => 'Lesson 3', 'module' => 'Advanced'],
// ['name' => 'Lesson 4', 'module' => 'Advanced'],
// ]],
// ['Basics', [
// ['name' => 'Lesson 5', 'module' => 'Basics'],
// ]],
// ];Full signature: sectionBy($callback, $preserveKeys, $sectionKey, $itemsKey)
Create a Paginator instance for the items in the collection.
collect($posts)->simplePaginate(5);This paginates the contents of $posts with 5 items per page. simplePaginate accepts quite some options, head over to the Laravel docs for an in-depth guide.
simplePaginate(int $perPage = 15, string $pageName = 'page', int $page = null, int $total = null, array $options = [])
For a in-depth guide on pagination, check out the Laravel docs.
Slice the values out from a collection before the given callback is true. If the optional parameter $preserveKeys as true is passed, it will preserve the original keys.
collect([20, 51, 10, 50, 66])->sliceBefore(function($item) {
return $item > 50;
}); // return collect([[20],[51, 10, 50], [66])Extract the tail from a collection. So everything except the first element. It's a shorthand for slice(1)->values(), but nevertheless very handy. If the optional parameter $preserveKeys as true is passed, it will preserve the keys and fallback to slice(1).
collect([1, 2, 3])->tail(); // return collect([2, 3])Transform a collection into an array with pairs.
$collection = collect(['a' => 'b', 'c' => 'd', 'e' => 'f'])->toPairs();
$collection->toArray(); // returns ['a', 'b'], ['c', 'd'], ['e', 'f']The goal of transpose is to rotate a multidimensional array, turning the rows into columns and the columns into rows.
collect([
['Jane', 'Bob', 'Mary'],
['jane@example.com', 'bob@example.com', 'mary@example.com'],
['Doctor', 'Plumber', 'Dentist'],
])->transpose()->toArray();
// [
// ['Jane', 'jane@example.com', 'Doctor'],
// ['Bob', 'bob@example.com', 'Plumber'],
// ['Mary', 'mary@example.com', 'Dentist'],
// ]Returns true if the given $callback returns true for every item. If $callback is a string or an array, regard it as a validation rule.
collect(['foo', 'foo'])->validate(function ($item) {
return $item === 'foo';
}); // returns true
collect(['sebastian@spatie.be', 'bla'])->validate('email'); // returns false
collect(['sebastian@spatie.be', 'freek@spatie.be'])->validate('email'); // returns trueCreate a new collection with the specified amount of items.
Collection::withSize(1)->toArray(); // return [1];
Collection::withSize(5)->toArray(); // return [1,2,3,4,5];Please see CHANGELOG for more information what has changed recently.
$ composer testPlease see CONTRIBUTING for details.
If you discover any security related issues, please email freek@spatie.be instead of using the issue tracker.
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.
The MIT License (MIT). Please see License File for more information.