Collection
Collection
Fluent, chainable wrapper around arrays. Namespace Zero\Lib\Support\Collection (aliased as Collection). Build with the global collect() helper or Collection::make().
use Zero\Lib\Support\Collection;
collect([1, 2, 3, 4, 5])
->filter(fn ($v) => $v > 2)
->map(fn ($v) => $v * 10)
->values()
->all(); // [30, 40, 50]Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, so count($c), foreach ($c as ...), $c[$key], and json_encode($c) work directly.
Topics: Building · Conversion · Iteration · Filtering · Querying · Mutation · Slicing · Reshaping · Set Operations · Sorting · Aggregates · Conditional
Building
Static factories on Collection. Implementation: top of Collection.php.
collect(mixed $items = []): Collection / Collection::make(iterable $items)
collect([1, 2, 3])->count(); // 3
Collection::make(['a' => 1])->all(); // ['a' => 1]Collection::wrap(mixed $value): Collection
Wrap any value.
Collection::wrap('a')->all(); // ['a']
Collection::wrap(null)->all(); // []Collection::range(int $from, int $to): Collection
Collection::range(1, 3)->all(); // [1, 2, 3]Collection::times(int $number, ?callable $callback = null): Collection
Collection::times(3, fn ($i) => $i * 2)->all(); // [2, 4, 6]Conversion
Implementation: Concerns/Collection/Conversion.php.
all(): array
collect([1, 2, 3])->all(); // [1, 2, 3]toArray(): array
Recursively convert nested Collections / JsonSerializable.
collect([collect([1, 2])])->toArray(); // [[1, 2]]toJson(int $flags = 0): string / jsonSerialize(): array
collect([1, 2])->toJson(); // '[1,2]'
json_encode(collect([1, 2])); // '[1,2]'count(): int / isEmpty(): bool / isNotEmpty(): bool
collect([1, 2])->count(); // 2
collect([])->isEmpty(); // true
collect([1])->isNotEmpty(); // true
count(collect([1, 2, 3])); // 3keys(): Collection / values(): Collection
collect(['a' => 1, 'b' => 2])->keys()->all(); // ['a', 'b']
collect(['a' => 1, 'b' => 2])->values()->all(); // [1, 2]ArrayAccess / getIterator()
$c = collect(['a' => 1]);
$c['a']; // 1
foreach ($c as $k => $v) { /* ... */ }Iteration
Implementation: Concerns/Collection/Iteration.php.
map(callable $cb): Collection
collect([1, 2, 3])->map(fn ($v) => $v * 2)->all(); // [2, 4, 6]mapWithKeys(callable $cb): Collection
collect([['id' => 1, 'n' => 'a']])
->mapWithKeys(fn ($v) => [$v['id'] => $v['n']])
->all(); // [1 => 'a']mapSpread(callable $cb): Collection
Spread each item's values as positional arguments.
collect([[1, 2], [3, 4]])
->mapSpread(fn ($a, $b) => $a + $b)
->all(); // [3, 7]flatMap(callable $cb): Collection
Map then collapse.
collect([[1, 2], [3]])->flatMap(fn ($v) => $v)->all(); // [1, 2, 3]each(callable $cb): self
Iterate; return false from the callback to stop.
collect([1, 2, 3])->each(function ($v) { /* side effect */ });eachSpread(callable $cb): self
collect([[1, 2], [3, 4]])->eachSpread(fn ($a, $b) => /* ... */);reduce(callable $cb, $initial = null): mixed
collect([1, 2, 3])->reduce(fn ($carry, $v) => $carry + $v, 0); // 6pluck(string|array|null $value, $key = null): Collection
collect([['id' => 1], ['id' => 2]])->pluck('id')->all(); // [1, 2]partition(callable $cb): Collection
Returns a Collection of two Collections.
[$evens, $odds] = collect([1, 2, 3, 4])->partition(fn ($v) => $v % 2 === 0);
$evens->all(); // [1 => 2, 3 => 4]
$odds->all(); // [0 => 1, 2 => 3]keyBy(callable|string $keyBy): Collection
collect([['id' => 1], ['id' => 2]])->keyBy('id')->keys()->all(); // [1, 2]groupBy(callable|string $groupBy): Collection
Each group is itself a Collection.
collect([['t' => 'a'], ['t' => 'a'], ['t' => 'b']])
->groupBy('t')
->count(); // 2Filtering
Implementation: Concerns/Collection/Filtering.php.
filter(?callable $cb = null): Collection
Without a callback, drops falsy values.
collect([0, 1, 2])->filter()->values()->all(); // [1, 2]
collect([1, 2, 3, 4])->filter(fn ($v) => $v > 2)->values()->all(); // [3, 4]reject(callable $cb): Collection
Inverse of filter.
collect([1, 2, 3, 4])->reject(fn ($v) => $v % 2 === 0)->values()->all(); // [1, 3]where(string $key, $operator = null, $value = null): Collection
Two-argument form is =. Operators: =, ==, ===, !=, !==, <>, >, >=, <, <=.
$users = [['active' => true], ['active' => false]];
collect($users)->where('active', true)->count(); // 1
collect([['n' => 5], ['n' => 1]])->where('n', '>', 3)->count(); // 1whereIn(string $key, iterable $values): Collection / whereNotIn(...)
collect([['t' => 'a'], ['t' => 'b'], ['t' => 'c']])
->whereIn('t', ['a', 'c'])
->count(); // 2whereNotNull(?string $key = null): Collection / whereNull(...)
collect([1, null, 2])->whereNotNull()->values()->all(); // [1, 2]
collect([['n' => 1], ['n' => null]])->whereNull('n')->count(); // 1only(array|string $keys): Collection / except(...)
collect(['a' => 1, 'b' => 2, 'c' => 3])->only(['a', 'c'])->all(); // ['a' => 1, 'c' => 3]contains($key, $operator = null, $value = null): bool
Scalar / closure / where form.
collect([1, 2, 3])->contains(2); // true
collect([1, 2, 3])->contains(fn ($v) => $v > 2); // true
collect([['t' => 'a']])->contains('t', 'a'); // truehas(string|int|array $key): bool
Returns true only when every key exists.
collect(['a' => 1])->has('a'); // true
collect(['a' => 1])->has(['a', 'b']); // falseQuerying
Implementation: Concerns/Collection/Querying.php.
first(?callable $cb = null, $default = null): mixed / last(...)
collect([1, 2, 3])->first(); // 1
collect([1, 2, 3])->first(fn ($v) => $v > 1); // 2
collect([1, 2, 3])->last(); // 3get(string|int $key, $default = null): mixed
collect(['a' => 1])->get('a'); // 1
collect([])->get('x', 'fallback'); // 'fallback'search(mixed $value, bool $strict = false): mixed
Returns the matching key (or false). Accepts a closure.
collect(['a', 'b', 'c'])->search('b'); // 1
collect([1, 2, 3])->search(fn ($v) => $v === 2); // 1random(?int $number = null, bool $preserveKeys = false): mixed
collect([1, 2, 3, 4, 5])->random(); // single item
collect([1, 2, 3, 4, 5])->random(3); // Collection of 3 itemsMutation
These mutate the underlying items in place and return $this. Implementation: Concerns/Collection/Mutation.php.
put(string|int $key, mixed $value): self
collect()->put('a', 1)->all(); // ['a' => 1]pull(string|int $key, $default = null): mixed
Read and remove.
$c = collect(['a' => 1, 'b' => 2]);
$c->pull('a'); // 1; $c->all() === ['b' => 2]push(mixed ...$values): self
collect([1])->push(2, 3)->all(); // [1, 2, 3]prepend(mixed $value, $key = null): self
collect([2, 3])->prepend(1)->all(); // [1, 2, 3]
collect(['b' => 2])->prepend(1, 'a')->all(); // ['a' => 1, 'b' => 2]pop(int $count = 1): mixed / shift(int $count = 1): mixed
With $count = 1 returns the item; otherwise returns a Collection.
collect([1, 2, 3])->pop(); // 3
collect([1, 2, 3])->shift(); // 1forget(string|int|array $keys): self
collect(['a' => 1, 'b' => 2])->forget('a')->all(); // ['b' => 2]Slicing
Implementation: Concerns/Collection/Slicing.php.
take(int $limit): Collection
collect([1, 2, 3, 4])->take(2)->all(); // [1, 2]
collect([1, 2, 3, 4])->take(-2)->all(); // [3, 4]skip(int $count): Collection
collect([1, 2, 3, 4])->skip(2)->values()->all(); // [3, 4]slice(int $offset, ?int $length = null): Collection
collect([1, 2, 3, 4])->slice(1, 2)->values()->all(); // [2, 3]chunk(int $size): Collection
Returns a Collection of Collections.
collect([1, 2, 3, 4, 5])->chunk(2)->count(); // 3nth(int $step, int $offset = 0): Collection
collect([1, 2, 3, 4, 5, 6])->nth(2)->all(); // [1, 3, 5]
collect([1, 2, 3, 4, 5, 6])->nth(2, 1)->all(); // [2, 4, 6]Reshaping
Implementation: Concerns/Collection/Reshaping.php.
collapse(): Collection
Merge a list of arrays.
collect([[1, 2], [3]])->collapse()->all(); // [1, 2, 3]flatten(int $depth = PHP_INT_MAX): Collection
collect([1, [2, [3]]])->flatten()->all(); // [1, 2, 3]flip(): Collection
collect(['a', 'b'])->flip()->all(); // ['a' => 0, 'b' => 1]dot(): Collection / undot(): Collection
collect(['a' => ['b' => 1]])->dot()->all(); // ['a.b' => 1]
collect(['a.b' => 1])->undot()->all(); // ['a' => ['b' => 1]]reverse(): Collection
Preserves keys.
collect([1, 2, 3])->reverse()->values()->all(); // [3, 2, 1]zip(iterable ...$items): Collection
collect([1, 2])->zip([3, 4])->first()->all(); // [1, 3]Set Operations
Implementation: Concerns/Collection/SetOperations.php.
merge(iterable $items): Collection / mergeRecursive(iterable $items): Collection
collect([1, 2])->merge([3, 4])->all(); // [1, 2, 3, 4]concat(iterable $source): Collection
Append numerically (no key collision).
collect([1, 2])->concat([3])->all(); // [1, 2, 3]combine(iterable $values): Collection
Use this collection's values as keys, combine with $values.
collect(['a', 'b'])->combine([1, 2])->all(); // ['a' => 1, 'b' => 2]diff(iterable $items): Collection / diffKeys(iterable $items): Collection
collect([1, 2, 3])->diff([2])->values()->all(); // [1, 3]intersect(iterable $items): Collection / intersectByKeys(iterable $items): Collection
collect([1, 2, 3])->intersect([2, 3, 4])->values()->all(); // [2, 3]Sorting
Implementation: Concerns/Collection/Sorting.php.
sort(?callable $cb = null): Collection
collect([3, 1, 2])->sort()->values()->all(); // [1, 2, 3]sortBy(callable|string $cb, int $options = SORT_REGULAR, bool $descending = false): Collection
collect([['n' => 3], ['n' => 1]])
->sortBy('n')
->values()
->pluck('n')
->all(); // [1, 3]sortByDesc(callable|string $cb, int $options = SORT_REGULAR): Collection
collect([['n' => 1], ['n' => 3]])->sortByDesc('n')->values()->pluck('n')->all(); // [3, 1]sortDesc(): Collection
Without a key/callback.
collect([1, 3, 2])->sortDesc()->values()->all(); // [3, 2, 1]sortKeys(int $options = SORT_REGULAR, bool $descending = false): Collection
collect(['b' => 1, 'a' => 2])->sortKeys()->keys()->all(); // ['a', 'b']unique(callable|string|null $key = null, bool $strict = false): Collection
collect([1, 2, 2, 3])->unique()->values()->all(); // [1, 2, 3]
collect([['t' => 'a'], ['t' => 'a'], ['t' => 'b']])->unique('t')->count(); // 2duplicates(): Collection
Items that appear more than once.
collect([1, 2, 2, 3, 3])->duplicates()->count(); // 4shuffle(?int $seed = null): Collection
Seedable.
collect([1, 2, 3])->shuffle()->count(); // 3Aggregates
Implementation: Concerns/Collection/Aggregates.php.
sum(callable|string|null $cb = null): int|float
collect([1, 2, 3])->sum(); // 6
collect([['n' => 1], ['n' => 2]])->sum('n'); // 3avg(callable|string|null $cb = null): int|float|null (alias average)
collect([1, 2, 3, 4])->avg(); // 2.5min(callable|string|null $cb = null): mixed / max(...)
collect([3, 1, 2])->min(); // 1
collect([3, 1, 2])->max(); // 3median(callable|string|null $cb = null): int|float|null
collect([1, 2, 3])->median(); // 2
collect([1, 2, 3, 4])->median(); // 2.5implode(string $glue, ?string $key = null): string
collect(['a', 'b', 'c'])->implode(','); // 'a,b,c'
collect([['n' => 'a'], ['n' => 'b']])->implode(',', 'n'); // 'a,b'join(string $glue, string $finalGlue = ''): string
collect(['a', 'b', 'c'])->join(', ', ' and '); // 'a, b and c'Conditional
Implementation: Concerns/Collection/Conditional.php.
pipe(callable $cb): mixed
Forward the Collection through a callback.
collect([1, 2, 3])->pipe(fn ($c) => $c->sum()); // 6tap(callable $cb): self
Side effect; returns the Collection.
collect([1, 2])->tap(fn ($c) => logger("count={$c->count()}"))->count(); // 2when(mixed $cond, callable $cb, ?callable $default = null): self
Run $cb only when $cond is truthy.
collect([1, 2])->when(true, fn ($c) => $c->push(3))->all(); // [1, 2, 3]unless(mixed $cond, callable $cb, ?callable $default = null): self
collect([1])->unless(false, fn ($c) => $c->push(2))->all(); // [1, 2]whenEmpty(callable $cb, ?callable $default = null): self / whenNotEmpty(...)
collect([])->whenEmpty(fn ($c) => $c->push(1))->all(); // [1]
collect([1])->whenNotEmpty(fn ($c) => $c->push(2))->all(); // [1, 2]