Skip to content

Collections

Collections provide type-safe containers for domain objects with functional programming operations.

Characteristics

  • Type safety: Collections enforce element types at runtime
  • Functional operations: map, filter, reduce, each
  • Iterable: Works with foreach
  • Countable: Supports count()

Creating Typed Collections

Extend AbstractTypedCollection and specify the element type:

final class BooksCollection extends AbstractTypedCollection
{
    protected function type(): string
    {
        return Book::class;
    }
}

Usage

$books = new BooksCollection([$book1, $book2]);

// Access
$books->first();      // First element
$books->last();       // Last element
$books->count();      // Number of elements

// Functional operations
$titles = $books->map(fn (Book $book) => $book->getTitle()->getValue());
$available = $books->filter(fn (Book $book) => $book->getStatus()->isAvailable());

// Iteration
foreach ($books as $book) {
    echo $book->getTitle()->getValue();
}

Creating Collections

// From array
$books = BooksCollection::fromArray([$book1, $book2]);

// From map (transform raw data)
$books = BooksCollection::fromMap($rows, fn (array $row) => new Book(/* ... */));

Repository Usage

Repositories return typed collections:

interface BookRepository
{
    public function findAll(): BooksCollection;
    public function findBy(SpecificationInterface $spec): BooksCollection;
}

Available Operations

Collections provide operations grouped by capability:

Capability Methods
Readable first(), last(), isEmpty(), items(), values()
Functional map(), filter(), reduce(), each()
Transformable slice(), take(), sort(), reverse(), unique()
Searchable find(), findKey(), findAll(), indexOf(), lastIndexOf()
Mutable add(), set(), remove(), clear()
Navigable key(), current(), next(), previous(), rewind()

Untyped Collections

For generic collections without type enforcement, extend AbstractCollection directly:

$items = AbstractCollection::fromArray([1, 'two', new Book()]);

Best Practices

  • One collection per entity type
  • Return collections from repositories, not raw arrays
  • Prefer map/filter over imperative loops
  • Let the collection enforce element types