Skip to content

Collection

Viames Marino edited this page Feb 26, 2026 · 2 revisions

Pair framework: Collection

Pair\Orm\Collection is the in-memory collection used across Pair ORM and services.

It implements:

  • ArrayAccess
  • Iterator
  • Countable

This class is inspired by Eloquent collections, but behavior is the one implemented in Pair source code.

Quick behavior notes

  • Some methods return a new collection (immutable style).
  • Some methods mutate the current instance and return $this.
  • Methods are designed mainly for ActiveRecord/object-like items, but many also work with arrays/scalars.

At least one full usage example

use Pair\Orm\Collection;

$orders = new Collection([
    (object)['id' => 1, 'status' => 'paid',    'total' => 120.50],
    (object)['id' => 2, 'status' => 'pending', 'total' =>  45.00],
    (object)['id' => 3, 'status' => 'paid',    'total' =>  80.00],
    (object)['id' => 4, 'status' => 'failed',  'total' =>  10.00],
]);

$paidTotals = $orders
    ->whereIn('status', ['paid']) // filter
    ->sortBy('total')             // sort ascending
    ->pluck('total')              // get totals only
    ->values();                   // reset numeric keys

echo $paidTotals->toJson(JSON_PRETTY_PRINT);
// [80, 120.5]

Method reference (complete)

1) Construction, wrapping, exporting

  • __construct(?array $array = null) initializes items ((array)$array cast).
  • collect(): Collection returns a new collection with the same items.
  • copy(bool $deep = false): static shallow/deep copy; deep copy clones nested objects when possible.
  • all(): array returns raw internal array.
  • toArray(): array converts items; ActiveRecord items are converted via toArray().
  • toJson(int $options = 0): string JSON-encodes toArray().
  • static wrap($value): Collection wraps value into collection (if already collection, returns it).
  • static unwrap($value): mixed returns raw array for collection values, unchanged otherwise.
  • getIterator(): \Traversable returns ArrayIterator.

2) Add, set, remove, mutate

  • add(ActiveRecord $item): static appends an ActiveRecord.
  • push(...$values): static appends one or more values.
  • prepend($value, $key = null): static prepends at start; keyed prepend supported.
  • unshift($value, $key = null): Collection prepend alias with same behavior.
  • put($key, $value): static sets key/value.
  • getOrPut($key, $value): mixed gets by key, sets default if missing.
  • forget(int $position): static removes item by numeric position and reindexes keys.
  • pull($key): mixed gets value then removes it via forget(...).
  • pop(int $count = 1): mixed pops last item or multiple items.
  • shift(): ?ActiveRecord removes and returns first item.
  • merge(array|Collection $items): Collection mutates current collection via array_merge.

3) Access and key management

  • get($key, $default = null): mixed returns item or default.
  • keys(): static returns collection of keys.
  • values(): Collection returns collection with reset numeric keys.
  • keyBy(string|callable $key): Collection rekeys collection by field/callback.
  • key(): int iterator current position.
  • value(string $key): mixed returns $this->first()[$key].

4) Membership and existence

  • contains($key, $value = null): bool loose check by model instance or key/value.
  • containsStrict($key, $value = null): bool strict (===) version for key/value checks.
  • doesntContain($key, $value = null): bool negation of contains.
  • containsOneItem(): bool true when count is exactly 1.
  • has($key): bool checks key existence (single or variadic).
  • hasAny(mixed $key): bool true if any provided key exists.
  • isEmpty(): bool true when collection has no items.
  • isNotEmpty(): bool inverse of isEmpty().
  • search($value, bool $strict = false): mixed returns key or false.

5) Filtering and querying

  • filter(?callable $callback = null): Collection keeps matching items; without callback removes falsy values.
  • reject(callable $callback): Collection inverse filter.
  • where(string $key, $operator, $value = null): Collection comparison filter (=, !=, <, <=, >, >=).
  • whereStrict(string $key, $operator, $value = null): Collection strict equality/inequality comparisons.
  • whereIn(string $key, array $values, bool $strict = false): Collection
  • whereInStrict(string $key, array $values): Collection
  • whereNotIn(string $key, array $values, bool $strict = false): Collection
  • whereNotInStrict(string $key, array $values): Collection
  • whereBetween(string $key, array $values): Collection
  • whereNotBetween(string $key, array $values): Collection
  • whereNull(string $key): Collection
  • whereNotNull(string $key): Collection
  • whereInstanceOf(string $type): Collection
  • firstWhere(string $key, $value): mixed first match or null.
  • before(string $key, string $value): Collection items where $item[$key] < $value.
  • only(array $keys): Collection keeps only specified top-level keys.
  • except(array $keys): Collection removes specified top-level keys.

6) Positional slicing and pagination-like helpers

  • first(): mixed first item or null.
  • firstOrFail(): mixed first item or PairException.
  • last(): mixed last item.
  • slice(int $offset, ?int $length = null): static slices preserving keys.
  • skip(int $count): static alias for slice($count).
  • take(int $limit): static first N (or last N for negative limit).
  • forPage(int $page, int $perPage): Collection offset/limit extraction.
  • nth(int $step, int $offset = 0): Collection every n-th element.
  • chunk(int $size): Collection splits in fixed-size arrays.
  • chunkWhile(int $size): Collection currently same behavior as chunk.
  • split(int $numberOfGroups): static splits into balanced groups.

7) Transformations

  • map(callable $callback): static maps values, preserving original keys.
  • transform(callable $callback): Collection map-like transform with explicit key passing.
  • flatMap(callable $callback): Collection map then collapse one level.
  • flatten(int $depth = INF): Collection flattens nested Collection values.
  • collapse(): Collection merges nested collections by one level.
  • dot(): Collection flattens nested collections while preserving composite key intent.
  • pluck(string $value, ?string $key = null): Collection extracts field values.
  • append(string|array $attributes): static calls append(...) on each item and returns new collection.
  • groupBy(string|callable $key): Collection groups by field/callback.
  • flip(): Collection swaps keys and values.
  • pad(int $size, $value): Collection array_pad behavior.
  • multiply(int $times): Collection repeats each item times.
  • range(int $start, int $end): Collection returns integer range collection.

8) Combining and set-like operations

  • concat(array|Collection $values): Collection appends values and returns new collection.
  • combine(array $values): Collection uses current values as keys, external values as values.
  • intersect(array|Collection $items): Collection
  • intersectAssoc(array|Collection $items): Collection
  • union(array|Collection $items): Collection original keys/values preserved on collisions.
  • replace(array|Collection $items): Collection
  • replaceRecursive(array|Collection $items): Collection
  • zip(array|Collection $items): Collection pairs items by index.

9) Sorting and uniqueness

  • sort($callback = null) sort by callback or regular sort, keeps keys.
  • sortBy(array|string|Closure $key, int $options = SORT_REGULAR): Collection
  • sortDesc(): Collection reverse of sorted collection.
  • reverse(): static reverse order preserving keys.
  • unique(?string $key = null): Collection unique values (or unique by key).
  • uniqueStrict(): Collection strict unique (same implementation style as array_unique).
  • duplicates(): Collection duplicate values.
  • duplicatesStrict(): Collection strict duplicate comparison helper.

10) Aggregation and statistics

  • count(): int
  • countBy(string $key): Collection frequency map for key values.
  • sum(string $key): int sums numeric property values.
  • avg(?string $key = null): float sum / count.
  • min(string $key): mixed minimum plucked value.
  • mode(?string $key = null): mixed mode-like helper based on count frequencies.
  • percentage(callable $callback, int $precision = 2): float passing percentage.
  • reduce(callable $callback, $initial = null): mixed
  • reduceSpread(callable $callback, array $initial): Collection
  • implode(string $glue, ?string $key = null): string
  • join(string $glue, string $finalGlue = ''): string

11) Flow-control helpers

  • when(bool $value, callable $callback, callable $default): mixed
  • unless(bool $value, callable $callback, callable $default): mixed
  • whenEmpty(callable $callback, callable $default): mixed
  • whenNotEmpty(callable $callback, callable $default): mixed
  • unlessEmpty(callable $callback, callable $default): mixed alias of whenNotEmpty.
  • unlessNotEmpty(callable $callback, callable $default): mixed alias of whenEmpty.
  • every(callable $callback): bool all items satisfy condition.
  • each(callable $callback): void iterates with item + key.
  • eachSpread(callable $callback): void spreads nested arrays into callback args.
  • eachInstanceOf(string $type): void runtime type guard on all items.

12) Debug helpers

  • dump(): void var_dump($items).
  • dd(): void dumps then stops execution.

13) Iterator / ArrayAccess contract methods

Iterator:

  • current(): mixed
  • next(): void
  • rewind(): void
  • valid(): bool
  • key(): int

ArrayAccess:

  • offsetExists(mixed $key): bool
  • offsetGet($key): mixed
  • offsetSet($key, $value): void
  • offsetUnset($key): void

14) Internal (non-public) methods

  • private deepCopyValue(mixed $value): mixed recursive helper for copy(true).
  • protected sortByCallback(Closure $callback): array
  • protected sortByMultiple(array $keys): array
  • protected sortBySingle(string $key, int $options, mixed $a = null, mixed $b = null): int|array

Important implementation caveats

These notes reflect current source behavior:

  • random($number > 1) returns a collection of random keys, not random items.
  • where(...) does not normalize two-argument syntax (where('x', 10)), it expects operator/value style.
  • whereNull(...) delegates to where($key, null) and may not behave like SQL-style null filtering.
  • forget(...) reindexes numeric keys with array_values.
  • pull($key) internally calls forget(int $position); non-numeric keys can cause type issues.
  • sum(...) expects property-based objects and validates key/value on first item.

Additional short examples

Filter + aggregate:

$totalPaid = $orders
    ->where('status', '=', 'paid')
    ->sum('total');

Conditional pipeline:

$result = $orders->when(
    $orders->isNotEmpty(),
    fn ($c) => $c->sortBy('total')->take(3),
    fn ($c) => new Collection()
);

Set-like operations:

$a = new Collection([1, 2, 3]);
$b = new Collection([3, 4, 5]);

$intersection = $a->intersect($b)->values(); // [3]
$union = $a->union($b); // keeps existing keys/values from $a on conflicts

See also: ActiveRecord, Query, Model, Database, Form.

Clone this wiki locally