Collection API
Collection<E> is the base interface for ordered element collections (List and Set). It extends IteratorAggregate<int, E> and Countable, and provides element access, querying, aggregation, transformation, and ordering methods.
Element Access
first(): EReturns the first element. Throws NoSuchElementException if empty.
firstOrNull(): E|nullReturns the first element, or null if empty.
last(): EReturns the last element. Throws NoSuchElementException if empty.
lastOrNull(): E|nullReturns the last element, or null if empty.
single(): EReturns the single element. Throws NoSuchElementException if empty or more than one element.
singleOrNull(): E|nullReturns the single element. Returns null if empty or more than one element.
find(Closure $predicate): E|nullReturns the first element matching the predicate (E, int): bool, or null if no element matches. Uses early termination.
findLast(Closure $predicate): E|nullReturns the last element matching the predicate (E, int): bool, or null if no element matches.
expect(Closure $predicate): EReturns the first element matching the predicate (E, int): bool. Throws NoSuchElementException if no element matches. Uses early termination.
expectLast(Closure $predicate): EReturns the last element matching the predicate (E, int): bool. Throws NoSuchElementException if no element matches.
random(): EReturns a random element. Throws NoSuchElementException if empty.
randomOrNull(): E|nullReturns a random element, or null if empty.
Querying
contains(mixed $element): boolWhether the collection contains the value (strict comparison).
containsAll(iterable $elements): boolWhether the collection contains all provided values.
all(Closure $predicate): boolReturns true if all elements match the predicate. Predicate: (E, int): bool.
any(Closure $predicate): boolReturns true if any element matches. Predicate: (E, int): bool.
none(Closure $predicate): boolReturns true if no element matches. Predicate: (E, int): bool.
count(): intReturns the number of elements in the collection.
countWhere(Closure $predicate): intReturns the number of elements matching the predicate (E, int): bool.
isEmpty(): boolWhether the collection has no elements.
isNotEmpty(): boolWhether the collection has at least one element.
Aggregation
fold(mixed $initial, Closure $operation): RLeft fold. Accumulates a result starting from the initial value by applying (R, E): R to each element. Usage: $list->fold(0, fn($acc, $v) => $acc + $v).
reduce(Closure $operation): EReduce with a binary operation (E, E): E. Throws UnsupportedOperationException if empty.
reduceOrNull(Closure $operation): E|nullReduce, or null if empty.
sum(?Closure $selector = null): int|floatSum of all elements, or values returned by the selector (E, int): int|float.
avg(?Closure $selector = null): floatAverage. Optional selector (E, int): int|float. Throws if empty.
avgOrNull(?Closure $selector = null): float|nullAverage, or null if empty. Optional selector (E, int): int|float.
min(?Closure $selector = null): EElement with minimum value. With a selector (E, int): mixed, returns the element whose selector value is minimum. Throws if empty.
minOrNull(?Closure $selector = null): E|nullMinimum element, or null if empty. Optional selector (E, int): mixed.
max(?Closure $selector = null): EElement with maximum value. Optional selector (E, int): mixed. Throws if empty.
maxOrNull(?Closure $selector = null): E|nullMaximum element, or null if empty. Optional selector (E, int): mixed.
minOf(Closure $selector): mixedReturns the minimum value produced by the selector (E, int): mixed. Unlike min(), returns the selector value itself, not the element. Throws NoSuchElementException if empty.
minOfOrNull(Closure $selector): mixedReturns the minimum selector value, or null if empty.
maxOf(Closure $selector): mixedReturns the maximum value produced by the selector (E, int): mixed. Unlike max(), returns the selector value itself, not the element. Throws NoSuchElementException if empty.
maxOfOrNull(Closure $selector): mixedReturns the maximum selector value, or null if empty.
joinToString(
string $separator = ', ',
string $prefix = '',
string $postfix = '',
int $limit = -1,
string $truncated = '...',
?Closure $transform = null,
): stringJoins elements into a string. When $transform is provided, it is applied to each element (E, int): string before joining. Without a transform, elements are converted via (string) cast — scalars, null, and Stringable objects are supported. Throws ConversionException for non-stringable objects and arrays.
countBy(Closure $keySelector): ImmutableMap<NK, int>Groups elements by the key returned by the selector (E, int): NK and counts elements in each group. Returns an ImmutableMap where keys are group identifiers and values are counts.
Transformation
All transformation methods are marked #[NoDiscard] and always return immutable collections, regardless of whether the source is mutable or immutable.
filter(Closure $predicate): ImmutableList<E> | ImmutableSet<E>Filter by predicate (E, int): bool. Returns ImmutableList for lists, ImmutableSet for sets.
filterNotNull(): Collection<E>Filter out null elements.
filterInstanceOf(string $type): Collection<T>Filter elements that are instances of the given class or interface. $type is a class-string<T>. Enables PHPStan to narrow the generic type — e.g. Collection<Animal> becomes ImmutableList<Dog>.
map(Closure $transform): Collection<R>Transform each element. Closure: (E, int): R.
mapNotNull(Closure $transform): Collection<R>Transform each element with (E, int): R|null and exclude null results. Combines map and filterNotNull in a single operation.
flatMap(Closure $transform): Collection<R>Transform and flatten. Closure: (E, int): iterable<R>.
flatten(): Collection<mixed>Flatten a collection of iterables.
takeFirst(int $n = 1): Collection<E>First N elements.
takeLast(int $n = 1): Collection<E>Last N elements.
dropFirst(int $n = 1): Collection<E>All elements except the first N.
dropLast(int $n = 1): Collection<E>All elements except the last N.
takeWhile(Closure $predicate): Collection<E>Take elements while predicate is true.
dropWhile(Closure $predicate): Collection<E>Drop elements while predicate is true, return the rest.
takeLastWhile(Closure $predicate): Collection<E>Take elements from the end while predicate (E, int): bool is true.
dropLastWhile(Closure $predicate): Collection<E>Drop elements from the end while predicate (E, int): bool is true, return the rest.
distinct(): Collection<E>Unique elements by identity.
distinctBy(Closure $selector): Collection<E>Unique elements by selector (E, int): mixed value.
chunked(int $size): ListInterface<ListInterface<E>>Split into chunks of the given size. The last chunk may be smaller.
windowed(
int $size,
int $step = 1,
bool $partialWindows = false,
): ListInterface<ListInterface<E>>Returns a list of snapshots of a sliding window of the given size along this collection with the given step. When $partialWindows is true, includes smaller windows at the end.
zip(iterable $other): ListInterface<array{E, U}>Pair elements from two iterables at the same position. Result length equals the shorter input.
unzip(): array{ImmutableList<mixed>, ImmutableList<mixed>}Splits a collection of pairs into two lists — one from the first component ([0]), one from the second ([1]). Inverse of zip().
partition(Closure $predicate): array{Collection<E>, Collection<E>}Split into two collections — matching and non-matching.
groupBy(Closure $keySelector, ?Closure $valueTransform = null): Map<K, Collection<E>>Group elements by key selector (E, int): K. When a $valueTransform (E, int): V is provided, each element is transformed before being added to its group — the result is Map<K, ImmutableList<V>>.
intersect(iterable $other): ImmutableSet<E>Elements present in both this collection and the iterable. Returns a set (duplicates removed).
union(iterable $other): ImmutableSet<E>All elements from both this collection and the iterable. Returns a set (duplicates removed).
subtract(iterable $other): ImmutableSet<E>Elements present in this collection but not in the iterable. Returns a set (duplicates removed).
Ordering
All ordering methods returning new collections are marked #[NoDiscard].
sorted(): Collection<E>Natural ascending order.
sortedDesc(): Collection<E>Natural descending order.
sortedBy(Closure $selector): Collection<E>Sort by selector (E): R.
sortedByDesc(Closure $selector): Collection<E>Sort by selector, descending.
sortedWith(Closure $comparator): Collection<E>Sort by comparator (E, E): int.
reversed(): Collection<E>Reversed order.
shuffled(): Collection<E>Random order.
Iteration
forEach(Closure $action): CollectionExecute action (E, int): void for each element. Returns the collection for chaining.
Conversion
toMap(Closure $keySelector, ?Closure $valueTransform = null): ImmutableMap<K, V>Convert to an immutable map using key selector (E, int): K and optional value transform (E, int): V.
toList(): ImmutableList<E>Convert to an immutable list preserving iteration order.
toSet(): ImmutableSet<E>Convert to an immutable set (duplicates removed).
toArray(): array<int, E>Convert to a PHP array.
MutableCollection Methods
In addition to all Collection methods, MutableCollection<E> provides:
Tracking
tracked(): MutableTrackedCollection<E>Returns a tracked wrapper that shares the same underlying store. Each mutation method on the tracked wrapper returns a result with a $changed property indicating whether that operation modified the data:
$tracked = mutableSetOf([1, 2, 3])->tracked();
$tracked->add(4)->changed; // true
$tracked->add(4)->changed; // false - already presentNote: $changed is only available on the return value of mutation methods, not on the tracked wrapper itself.
Mutation
| Method | Description |
|---|---|
add(mixed $element): MutableCollection | Add a single element |
addFirst(mixed $element): MutableCollection | Add element at the beginning. For Sets: moves to front if already present. For Lists: always prepends |
addAll(iterable $elements): MutableCollection | Add all elements from iterable |
removeElement(mixed $element): MutableCollection | Remove first occurrence of element |
removeFirst(): MutableCollection | Remove the first element (no-op if empty) |
removeLast(): MutableCollection | Remove the last element (no-op if empty) |
removeIf(Closure $predicate): MutableCollection | Remove elements matching predicate |
removeAll(iterable $elements): MutableCollection | Remove all occurrences of given elements |
retainAll(iterable $elements): MutableCollection | Keep only elements present in iterable |
clear(): MutableCollection | Remove all elements |
In-place ordering
| Method | Description |
|---|---|
sort(): MutableCollection | Natural ascending order |
sortDesc(): MutableCollection | Natural descending order |
sortBy(Closure $selector): MutableCollection | By selector |
sortByDesc(Closure $selector): MutableCollection | By selector, descending |
sortWith(Closure $comparator): MutableCollection | By comparator |
reverse(): MutableCollection | Reverse in-place |
shuffle(): MutableCollection | Shuffle in-place |
ImmutableCollection Methods
In addition to all Collection methods, ImmutableCollection<E> provides (all #[NoDiscard]):
| Method | Description |
|---|---|
add(mixed $element): ImmutableCollection | New collection with element added |
addFirst(mixed $element): ImmutableCollection | New collection with element at the beginning. For Sets: moves to front if already present. For Lists: always prepends |
addAll(iterable $elements): ImmutableCollection | New collection with elements added |
removeElement(mixed $element): ImmutableCollection | New collection without first occurrence of element |
removeFirst(): ImmutableCollection | New collection without the first element (returns same collection if empty) |
removeLast(): ImmutableCollection | New collection without the last element (returns same collection if empty) |
removeIf(Closure $predicate): ImmutableCollection | New collection without matching elements |
removeAll(iterable $elements): ImmutableCollection | New collection without given elements |
retainAll(iterable $elements): ImmutableCollection | New collection with only given elements |