PHP Data Structures
A zero-dependency PHP library providing 6 typed data structures with 60+ methods: Stack, Queue, Collection, Set, TypedArray, and Pair.
Download
curl -OL https://ahmedhabib.com/libraries/download/php-data-structures
PHP Data Structures is a single-file, zero-dependency library for PHP 8.0+ that provides essential data structures missing from native PHP. Includes a LIFO Stack, FIFO Queue, fluent chainable Collection, unique-value Set, type-enforced TypedArray, and immutable key-value Pair. Every class is fully typed, implements Countable and IteratorAggregate where appropriate, and follows modern PHP conventions. Drop it into any project and start using it immediately.
PHP's native array is incredibly flexible, but that flexibility comes at the cost of intent — there's no way to express "this is a LIFO stack" or "only strings allowed" using plain arrays. PHP Data Structures fills this gap with six purpose-built classes that enforce access patterns and types at the language level. Inspired by data structure libraries in Java, Python, and JavaScript, each class implements standard PHP interfaces (Countable, IteratorAggregate, ArrayAccess, JsonSerializable) so they work seamlessly with count(), foreach, json_encode(), and bracket syntax. The library is a single file, requires zero dependencies, targets PHP 8.0+, and drops into any project — from CLI tools to REST APIs — without touching Composer.
-
Stack 9 methods
LIFO (Last In, First Out) — push one or more items onto the top, pop from the top, peek without removing, check if empty or contains a value, get size, clear all items, create from array, and iterate top-to-bottom via IteratorAggregate.
-
Queue 10 methods
FIFO (First In, First Out) — enqueue items to the back, dequeue from the front, peek at front or back without removing, check emptiness and membership, get size, clear, create from array, and iterate front-to-back.
-
Collection 25 methods
Fluent array wrapper — chainable map, filter, reduce, each, first/last with callbacks, sort, reverse, unique, chunk, flatten, pluck columns, groupBy key, contains check, slice/take/skip, merge collections, sum/avg/min/max aggregation, isEmpty, toArray, toJson, and full iteration support.
-
Set 12 methods
Unique-value collection — add values (duplicates ignored), remove, has membership check, mathematical union/intersect/diff operations returning new Sets, isSubsetOf check, size, isEmpty, clear, create from variadic args, and iteration over values.
-
TypedArray 10 methods
Type-enforced array — declare a scalar type (int, float, string, bool) or class name, add/set/get/remove with runtime type validation, ArrayAccess bracket syntax support, getType introspection, size, isEmpty, clear, create from variadic values, and throws InvalidArgumentException on type mismatch.
-
Pair 9 methods
Immutable key-value tuple — access key and value, create modified copies with withKey/withValue (original unchanged), convert to indexed or associative arrays, equality comparison with another Pair, create from array or static factory, and JSON serialization via JsonSerializable.
- Download PhpDataStructures.php
- Include or autoload it in your project
- Use the data structure classes: Stack, Queue, Collection, Set, TypedArray, Pair
require_once 'PhpDataStructures.php';
Stack (LIFO)
9 methods for last-in-first-out operations with push, pop, peek, and iteration
$stack = new Stack(); $stack->push('a', 'b', 'c'); $stack->peek(); // "c" (top item) $stack->pop(); // "c" (removed) $stack->pop(); // "b" $stack->size(); // 1
$stack = Stack::from([1, 2, 3]); $stack->contains(2); // true $stack->isEmpty(); // false $stack->size(); // 3 $stack->clear(); $stack->isEmpty(); // true
$stack = Stack::from(['x', 'y', 'z']); count($stack); // 3 foreach ($stack as $item) { echo $item; // z, y, x (top-first) }
Queue (FIFO)
10 methods for first-in-first-out operations with enqueue, dequeue, and peek
$q = new Queue(); $q->enqueue('first', 'second', 'third'); $q->dequeue(); // "first" $q->dequeue(); // "second" $q->size(); // 1
$q = Queue::from(['a', 'b', 'c']); $q->front(); // "a" $q->back(); // "c"
$q = Queue::from([10, 20, 30]); $q->contains(20); // true $q->isEmpty(); // false $q->clear(); $q->isEmpty(); // true
Collection (Fluent Array Wrapper)
25 chainable methods for transforming, filtering, aggregating, and slicing data
$result = Collection::of([1, 2, 3, 4, 5]) ->filter(fn($n) => $n > 2) ->map(fn($n) => $n * 10) ->toArray(); // [30, 40, 50]
$c = Collection::of([10, 20, 30]); $c->sum(); // 60 $c->avg(); // 20 $c->min(); // 10 $c->max(); // 30 $c->reduce(fn($carry, $n) => $carry + $n, 0); // 60
$users = Collection::of([
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
['name' => 'Carol', 'age' => 35],
]);
$users->first(); // ["name"=>"Alice", ...]
$users->first(fn($u) => $u['age'] > 28);
// ["name"=>"Bob", "age"=>30]$items = Collection::of([
['type' => 'fruit', 'name' => 'Apple'],
['type' => 'veg', 'name' => 'Carrot'],
]);
$items->pluck('name')->toArray();
// ["Apple", "Carrot"]
$items->groupBy('type');
// ["fruit" => Collection, "veg" => Collection]Collection::of([3, 1, 2, 1]) ->unique() // [3, 1, 2] ->sort() // [1, 2, 3] ->reverse() // [3, 2, 1] ->chunk(2); // [[3,2], [1]]
$c = Collection::of(['a', 'b', 'c', 'd', 'e']); $c->take(3)->toArray(); // ["a","b","c"] $c->skip(2)->toArray(); // ["c","d","e"] $c->merge(['f', 'g'])->toArray(); // ["a","b","c","d","e","f","g"]
$c = Collection::of([1, 2, 3]); $c->toJson(); // "[1,2,3]" $c->toArray(); // [1, 2, 3] $c->each(function($item, $key) { echo "{$key}: {$item}\n"; });
Set (Unique Values)
12 methods for unique-value collections with union, intersect, and diff operations
$set = new Set(); $set->add('php')->add('js')->add('php'); $set->size(); // 2 (no duplicates) $set->has('php'); // true $set->remove('js'); $set->toArray(); // ["php"]
$a = new Set([1, 2, 3]); $b = new Set([2, 3, 4]); $a->union($b)->toArray(); // [1, 2, 3, 4] $a->intersect($b)->toArray(); // [2, 3] $a->diff($b)->toArray(); // [1]
$small = new Set([1, 2]); $big = new Set([1, 2, 3, 4]); $small->isSubsetOf($big); // true $big->isSubsetOf($small); // false $tags = Set::from('php', 'mysql', 'redis'); $tags->size(); // 3
TypedArray (Type-Enforced Array)
10 methods for type-safe arrays that enforce a single type for all elements
$ids = TypedArray::of('int', 1, 2, 3); $ids->add(4); // OK $ids->get(0); // 1 $ids->set(0, 10); // replace index 0 $ids->add('five'); // InvalidArgumentException! // "Expected type [int], got [string]."
$users = new TypedArray(User::class); $users->add(new User('Alice')); // OK $users->add(new User('Bob')); // OK $users->add('not a user'); // throws! $users->getType(); // "User"
$names = TypedArray::of('string', 'a', 'b'); $names[] = 'c'; // append via [] $names[0] = 'x'; // overwrite index 0 count($names); // 3 foreach ($names as $name) { echo $name; // x, b, c }
Pair (Immutable Key-Value Tuple)
9 methods for immutable key-value pairs with equality checks and conversions
$pair = Pair::of('name', 'Alice'); $pair->key(); // "name" $pair->value(); // "Alice"
$original = Pair::of('color', 'blue'); $updated = $original->withValue('red'); $original->value(); // "blue" (unchanged) $updated->value(); // "red"
$p = Pair::of('lang', 'PHP'); $p->toArray(); // ["lang", "PHP"] $p->toAssoc(); // ["lang" => "PHP"] $p2 = Pair::from(['lang', 'PHP']); $p->equals($p2); // true json_encode($p); // {"key":"lang","value":"PHP"}