purrphp/pure-collection

Immutable type-safe collections for PHP

Maintainers

Package info

github.com/PurrPHP/pure-collection

pkg:composer/purrphp/pure-collection

Statistics

Installs: 8

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

1.0.0 2026-03-30 16:17 UTC

This package is auto-updated.

Last update: 2026-04-30 16:40:24 UTC


README

Type-safe collections for PHP 8. Type safety based on native PHP features, not static analyzers. Inspired by Kotlin collections.

Documentation

Problem scope

PHP has no native typed collections — only plain arrays. This makes it easy to accidentally mix types or corrupt key structure:

$uuids = [];
$uuids[] = Uuid::fromInteger('1');
$uuids[] = '00000000-0000-0000-0000-000000000001'; // wrong type, no error

$uuids[] = Uuid::fromInteger('2');
$uuids['validUuid'] = Uuid::fromInteger('3');       // mixed int/string keys

This library solves these problems by providing type-safe, semantically clear collections that reduce boilerplate and prevent mistakes at runtime.

Code structure

Inspired by Kotlin collections, the library provides three collection types:

  • List — ordered sequence with integer keys, duplicates allowed
  • Set — ordered sequence of unique values
  • Map — associative array (key → value)

Collections are immutable and return new object after each manipulation.

Hierarchy:

CollectionInterface
└── AbstractCollection
    ├── AbstractList               — ordered list (sequential integer keys)
    │   ├── AbstractSet            — deduplicates values on construction
    └── AbstractMap                — associative map (string/int keys)

Available Classes

Class Description
IntList Ordered list of integers
IntSet Ordered list of unique integers
IntNotEmptyList Same as IntList, throws on empty construction
IntNotEmptySet Same as IntSet, throws on empty construction
IntMap Associative (key → int) map
StringList Ordered list of strings
StringSet Ordered list of unique strings
StringNotEmptySet Same as StringSet, throws on empty construction
StringMap Associative (key → string) map

Installation

composer require purrphp/pure-collection

Usage

Lists

use Purr\Collection\IntList;

$numbers = new IntList(1, 2, 3, 4, 5);

$even    = $numbers->filter(fn(int $n): bool => $n % 2 === 0);
$doubled = $numbers->map(fn(int $n): int => $n * 2); // returns array
$sum     = $numbers->reduce(fn(int $carry, int $n): int => $carry + $n, 0);
$sorted  = $numbers->sorted(fn(int $a, int $b): int => $b <=> $a);

$numbers->count();      // 5
$numbers->isEmpty();    // false
$numbers->isNotEmpty(); // true
$numbers->max();        // 5
$numbers->min();        // 1

Sets (unique values)

use Purr\Collection\IntSet;
use Purr\Collection\StringSet;

$set = new IntSet(1, 2, 3, 2, 1); // duplicates are removed
$set->toArray();                   // [1, 2, 3]

$ids = IntSet::fromString('1,2,3', separator: ',');
$ids->join(',');                   // "1,2,3"

$tags = new StringSet('php', 'oop', 'php');
$tags->toArray();                  // ['php', 'oop']
$tags->sortedAlphabetically()->toArray(); // ['oop', 'php']

$a = new StringSet('a', 'b', 'c');
$b = new StringSet('b', 'c', 'd');
$a->diff($b)->toArray();           // ['a']

Maps

use Purr\Collection\IntMap;

$map = new IntMap(...['a' => 1, 'b' => 2, 'c' => 3]);

$map->filter(fn(int $v): bool => $v > 1)->toArray(); // ['b' => 2, 'c' => 3]
$map->groupBy(fn(int $v): string => $v % 2 === 0 ? 'even' : 'odd');

Common Operations

All collections implement CollectionInterface. See the full reference:

Extending

To create a custom typed collection, extend AbstractList, AbstractSet, or AbstractMap. See Architecture Decisions for decisions motivation and detailed guide for custom implementation.

use Purr\Collection\AbstractSet;

/** @template-extends AbstractSet<\DateTimeImmutable> */
class DateTimeSet extends AbstractSet
{
    public function __construct(\DateTimeImmutable ...$dates)
    {
        parent::__construct($dates);
    }
     protected function isSupportedType(mixed $value): bool
    {
        return $value instanceof \DateTimeImmutable;
    }

    protected function getId(mixed $value): int|string
    {
        return $value->getTimeStamp();
    }
}

Development

composer install

composer test        # Run tests
composer analyse     # Static analysis
composer cs-check    # Code style check
composer cs-fix      # Fix code style
composer check       # All checks

With Docker / Make

make test       # Run tests
make analyse    # Static analysis
make cs-check   # Code style check
make check      # All checks
make shell      # Open shell in dev container

License

MIT — see LICENSE.