← All docs

SPL

Standard PHP Library interfaces, exceptions, and runtime-backed container classes.

elephc ships the SPL pieces that are needed by supported PHP code today: iterator/counting/access interfaces, the SPL exception hierarchy, autoload and introspection helpers, the Phase 4 container classes, the Phase 5 storage iterator/decorator foundations, the Phase 6 heap/object-storage classes, and the Phase 8 file/directory iterators. This includes EmptyIterator, InternalIterator, ArrayIterator, ArrayObject, IteratorIterator, LimitIterator, NoRewindIterator, InfiniteIterator, filter/cache decorators FilterIterator, CallbackFilterIterator, RegexIterator, and CachingIterator, the multi-source decorators AppendIterator and MultipleIterator, the recursive family RecursiveArrayIterator, RecursiveFilterIterator, RecursiveCallbackFilterIterator, RecursiveRegexIterator, RecursiveIteratorIterator, and RecursiveCachingIterator, the filesystem classes SplFileInfo, SplFileObject, SplTempFileObject, DirectoryIterator, FilesystemIterator, GlobIterator, and RecursiveDirectoryIterator, and ParentIterator, plus SplHeap, SplMaxHeap, SplMinHeap, SplPriorityQueue, and SplObjectStorage.

SPL names live in the global namespace, matching PHP. They are available without imports or runtime extensions.

Interfaces

The compiler injects these SPL-related interfaces:

InterfaceNotes
TraversableMarker interface for iterable objects
IteratorRequires current(), key(), next(), valid(), rewind()
IteratorAggregateRequires getIterator(): Traversable
OuterIteratorExtends Iterator with getInnerIterator()
RecursiveIteratorExtends Iterator with recursive traversal hooks
SeekableIteratorExtends Iterator with seek()
Countablecount($obj) dispatches to count()
ArrayAccessSubscript syntax dispatches to offset methods
SplObserver, SplSubjectObserver/subject contracts

The full interface method signatures are listed in Classes.

Exceptions

The SPL exception hierarchy is built in, so user code can throw and catch these types directly:

ParentBuilt-in subclasses
LogicExceptionBadFunctionCallException, BadMethodCallException, DomainException, InvalidArgumentException, LengthException, OutOfRangeException
RuntimeExceptionOutOfBoundsException, OverflowException, RangeException, UnderflowException, UnexpectedValueException

They inherit the standard Exception constructor and Throwable API. Catch matching follows PHP’s normal class hierarchy rules.

Container Classes

The Phase 4 SPL containers and Phase 5 storage/decorator iterators are built-in classes. SplDoublyLinkedList, SplStack, SplQueue, and SplFixedArray use dedicated runtime storage; ArrayIterator and ArrayObject use compiler-managed keys/values storage over boxed mixed cells; the iterator decorators forward to one or more Iterator objects:

ClassParentInterfaces
SplDoublyLinkedList-Iterator, Countable, ArrayAccess
SplStackSplDoublyLinkedListinherited from parent
SplQueueSplDoublyLinkedListinherited from parent
SplFixedArray-IteratorAggregate, ArrayAccess, Countable, JsonSerializable
SplHeap-Iterator, Countable
SplMaxHeapSplHeapinherited from parent
SplMinHeapSplHeapinherited from parent
SplPriorityQueue-Iterator, Countable
SplObjectStorage-Iterator, Countable, ArrayAccess
SplFileInfo-Stringable
SplFileObjectSplFileInfoRecursiveIterator, SeekableIterator
SplTempFileObjectSplFileObjectinherited from parent
DirectoryIteratorSplFileInfoIterator, SeekableIterator
FilesystemIteratorDirectoryIteratorinherited from parent
GlobIteratorFilesystemIteratorCountable
RecursiveDirectoryIteratorFilesystemIteratorRecursiveIterator
RecursiveCachingIteratorCachingIteratorRecursiveIterator
EmptyIterator-Iterator
InternalIterator-Iterator
ArrayIterator-Iterator, ArrayAccess, SeekableIterator, Countable
ArrayObject-IteratorAggregate, ArrayAccess, Countable
IteratorIterator-OuterIterator
LimitIteratorIteratorIteratorinherited from parent
NoRewindIteratorIteratorIteratorinherited from parent
InfiniteIteratorIteratorIteratorinherited from parent
FilterIteratorIteratorIteratorinherited from parent
CallbackFilterIteratorFilterIteratorinherited from parent
RegexIteratorFilterIteratorinherited from parent
CachingIteratorIteratorIteratorArrayAccess, Countable, Stringable
RecursiveArrayIteratorArrayIteratorRecursiveIterator
RecursiveFilterIteratorFilterIteratorRecursiveIterator
RecursiveCallbackFilterIteratorCallbackFilterIteratorRecursiveIterator
RecursiveRegexIteratorRegexIteratorRecursiveIterator
RecursiveIteratorIterator-OuterIterator
ParentIteratorRecursiveFilterIteratorinherited from parent
AppendIteratorIteratorIteratorinherited from parent
MultipleIterator-Iterator

Container slots store mixed, so scalar and object values can be mixed in the same container. Runtime ownership is handled by the SPL helpers, including cleanup when the owning object is released.

SplDoublyLinkedList

Supported methods:

MethodNotes
push(mixed $value): voidAppend to the tail
pop(): mixedRemove from the tail
unshift(mixed $value): voidInsert at the head
shift(): mixedRemove from the head
add(int $index, mixed $value): voidInsert at an index
top(): mixedRead the tail
bottom(): mixedRead the head
count(): intNumber of stored values
isEmpty(): boolWhether the list is empty
setIteratorMode(int $mode): voidSet iterator flags
getIteratorMode(): intRead iterator flags
rewind(), current(), key(), next(), prev(), valid()Iterator operations
offsetExists(), offsetGet(), offsetSet(), offsetUnset()ArrayAccess backing
serialize(), unserialize(string $data): voidLegacy SPL list payload round-trip
__serialize(), __unserialize(array $data): voidPHP 7.4+ array state round-trip
__debugInfo(): arrayDebug state with flags and list contents

Supported constants:

ConstantValue
IT_MODE_FIFO0
IT_MODE_LIFO2
IT_MODE_DELETE1
IT_MODE_KEEP0
<?php
$list = new SplDoublyLinkedList();
$list->push("a");
$list->push(2);
$list[] = "c";

$list->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO);

foreach ($list as $index => $value) {
    echo $index;
    echo ":";
    echo $value;
    echo "\n";
}

IT_MODE_FIFO, IT_MODE_LIFO, and IT_MODE_DELETE are honored during iteration.

SplStack

SplStack extends SplDoublyLinkedList and uses the same runtime storage. It inherits the list methods and constants, with stack-style LIFO usage:

<?php
$stack = new SplStack();
$stack->push("first");
$stack->push("second");

echo $stack->pop();   // second
echo $stack->top();   // first

SplQueue

SplQueue extends SplDoublyLinkedList and adds queue aliases:

MethodBacking behavior
enqueue(mixed $value): voidSame storage path as push()
dequeue(): mixedSame storage path as shift()
<?php
$queue = new SplQueue();
$queue->enqueue("first");
$queue->enqueue("second");

echo $queue->dequeue(); // first

SplFixedArray

Supported methods:

MethodNotes
__construct(int $size = 0)Allocate fixed-size storage
__wakeup(): voidPHP wakeup hook
fromArray(array $array, bool $preserveKeys = true): SplFixedArrayBuild a fixed array from PHP array data
__serialize(): arrayReturns the same indexed values as toArray()
__unserialize(array $data): voidReplaces storage with packed source values
count(): intCurrent size
getIterator(): IteratorReturns an InternalIterator over live fixed-array storage
getSize(): intCurrent size
setSize(int $size): voidResize storage
offsetExists(mixed $index): boolFalse for invalid, unset, or null slots
offsetGet(mixed $index): mixedReads unset slots as null; invalid offsets throw
offsetSet(mixed $index, mixed $value): voidWrites valid integer offsets
offsetUnset(mixed $index): voidResets a valid slot to null
toArray(): arrayReturns an indexed array copy
jsonSerialize(): arrayReturns the same array shape as toArray()
<?php
$fixed = new SplFixedArray(2);
$fixed[0] = "left";
$fixed[1] = "right";

echo $fixed->getSize();
echo $fixed[0];

$fixed->setSize(3);
$fixed[2] = "tail";

Heaps, priority queues, and object storage

Supported heap methods:

ClassMethods
SplHeapabstract compare(mixed $value1, mixed $value2): int, insert(mixed $value): bool, extract(): mixed, top(): mixed, count(): int, isEmpty(): bool, rewind(), current(), key(), next(), valid(), recoverFromCorruption(): bool, isCorrupted(): bool, __debugInfo(): array
SplMaxHeapInherits SplHeap; compares larger values first
SplMinHeapInherits SplHeap; compares smaller values first
SplPriorityQueuecompare(mixed $priority1, mixed $priority2): int, insert(mixed $value, mixed $priority): bool, setExtractFlags(int $flags): void, getExtractFlags(): int, extract(): mixed, top(): mixed, count(): int, isEmpty(): bool, rewind(), current(), key(), next(), valid(), recoverFromCorruption(): bool, isCorrupted(): bool, __debugInfo(): array

SplPriorityQueue supports these extraction constants:

ConstantValue
EXTR_DATA1
EXTR_PRIORITY2
EXTR_BOTH3
<?php
$heap = new SplMaxHeap();
$heap->insert(3);
$heap->insert(1);
$heap->insert(5);

while (!$heap->isEmpty()) {
    echo $heap->extract();
}

$queue = new SplPriorityQueue();
$queue->insert("low", 1);
$queue->insert("high", 10);
$queue->setExtractFlags(SplPriorityQueue::EXTR_BOTH);

$item = $queue->extract();
echo $item["data"];
echo $item["priority"];

SplHeap and SplPriorityQueue iterators are destructive, matching PHP SPL: next() removes the current top value. User subclasses of SplHeap can override protected compare() to define their own ordering.

Supported SplObjectStorage methods:

MethodNotes
attach(mixed $object, mixed $info): voidAttach or update an object/info pair
detach(mixed $object): voidRemove an attached object
contains(mixed $object): boolStrict identity lookup
addAll(SplObjectStorage $storage): voidAttach all pairs from another storage
removeAll(SplObjectStorage $storage): voidDetach all objects found in another storage
removeAllExcept(SplObjectStorage $storage): voidKeep only objects found in another storage
getInfo(): mixed, setInfo(mixed $info): voidRead or write info at the iterator position
count(): intNumber of attached objects
rewind(), valid(), key(), current(), next(), seek(int $offset): voidIterator operations
offsetExists(), offsetGet(), offsetSet(), offsetUnset()ArrayAccess over object info
getHash(mixed $object): stringStable decimal hash for objects attached to this storage
serialize(), unserialize(string $data): void, __serialize(), __unserialize(array $data): void, __debugInfo(): arrayLightweight state/debug hooks
<?php
class Node {
    public int $id;

    public function __construct(int $id) {
        $this->id = $id;
    }
}

$left = new Node(1);
$right = new Node(2);

$storage = new SplObjectStorage();
$storage->attach($left, "left");
$storage[$right] = "right";

foreach ($storage as $index => $node) {
    echo $index;
    echo ":";
    echo $storage[$node];
}

SplObjectStorage stores object handles and info payloads in per-instance storage. Releasing the storage object releases the arrays and handles it owns.

Storage iterators

Supported methods:

ClassMethods
EmptyIteratorcurrent(), key(), next(), rewind(), valid()
ArrayIterator__construct(array $array = [], int $flags = 0), current(), key(), next(), rewind(), valid(), seek(int $offset): void, count(): int, offsetExists(), offsetGet(), offsetSet(), offsetUnset(), append(), getArrayCopy()
ArrayObject__construct(array $array = [], int $flags = 0), getIterator(): ArrayIterator, count(): int, offsetExists(), offsetGet(), offsetSet(), offsetUnset(), append(), getArrayCopy()
IteratorIterator__construct(Traversable $iterator, ?string $class = null), current(), key(), next(), rewind(), valid(), getInnerIterator(): ?Iterator
LimitIterator__construct(Iterator $iterator, int $offset = 0, int $limit = -1), rewind(), next(), valid(), seek(int $offset): void, getPosition(): int, plus inherited forwarding methods
NoRewindIterator__construct(Iterator $iterator), rewind() no-op, plus inherited forwarding methods
InfiniteIterator__construct(Iterator $iterator), next() cycles to the start when the inner iterator is exhausted, plus inherited forwarding methods
FilterIterator__construct(Iterator $iterator), abstract accept(): bool, rewind(), next(), plus inherited forwarding methods
CallbackFilterIterator__construct(Iterator $iterator, callable $callback), accept(): bool calling the callback as callback(current, key, inner)
RegexIterator__construct(Iterator $iterator, string $pattern, int $mode = RegexIterator::MATCH, int $flags = 0, int $pregFlags = 0), accept(), current(), key(), getMode(), setMode(), getFlags(), setFlags(), getRegex(), getPregFlags(), setPregFlags()
CachingIterator__construct(Iterator $iterator, int $flags = CachingIterator::CALL_TOSTRING), rewind(), valid(), next(), current(), key(), hasNext(), __toString(), getFlags(), setFlags(int $flags): void, getCache(), count(), offsetExists(), offsetGet(), offsetSet(), offsetUnset()
SplFileInfo__construct(string $filename), __toString(), getPath(), getFilename(), getExtension(), getBasename(string $suffix = ""), getPathname(), stat/predicate helpers, getFileInfo(), getPathInfo(), openFile(), setFileClass(), setInfoClass()
SplFileObject__construct(string $filename, string $mode = "r", bool $useIncludePath = false, mixed $context = null), line iterator methods, eof(), fgets(), fgetc(), fread(), fwrite(), fseek(), ftell(), fstat(), CSV-control helpers, hasChildren(), getChildren()
SplTempFileObject__construct(int $maxMemory = 2097152), plus inherited SplFileObject methods
DirectoryIterator__construct(string $directory), current(), key(), next(), rewind(), seek(int $offset): void, valid(), isDot(), plus inherited SplFileInfo methods
FilesystemIterator__construct(string $directory, int $flags = FilesystemIterator::SKIP_DOTS), current(), key(), getFlags(), setFlags(int $flags): void, plus inherited directory iteration
GlobIterator__construct(string $pattern, int $flags = 0), count(), plus inherited filesystem iteration
RecursiveArrayIterator__construct(array|object $array = [], int $flags = 0), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited ArrayIterator methods
RecursiveFilterIterator__construct(RecursiveIterator $iterator), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited FilterIterator methods
RecursiveCallbackFilterIterator__construct(RecursiveIterator $iterator, callable $callback), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited callback filtering
RecursiveRegexIterator__construct(RecursiveIterator $iterator, string $pattern, int $mode = RecursiveRegexIterator::MATCH, int $flags = 0, int $pregFlags = 0), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited regex filtering
RecursiveDirectoryIterator__construct(string $directory, int $flags = 0), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited filesystem iteration
RecursiveCachingIterator__construct(RecursiveIterator $iterator, int $flags = CachingIterator::CALL_TOSTRING), hasChildren(): bool, getChildren(): ?RecursiveIterator, plus inherited caching methods
RecursiveIteratorIterator__construct(RecursiveIterator $iterator, int $mode = RecursiveIteratorIterator::LEAVES_ONLY, int $flags = 0), rewind(), valid(), current(), key(), next(), getDepth(): int, getInnerIterator(): ?Iterator, getSubIterator(int $level = -1): ?RecursiveIterator
ParentIterator__construct(RecursiveIterator $iterator), accept(): bool, getChildren(): ?RecursiveIterator, plus inherited recursive filtering
AppendIterator__construct(), append(Iterator $iterator): void, rewind(), valid(), current(), key(), next(), getInnerIterator(): ?Iterator, getIteratorIndex(): int|string|null, getArrayIterator(): ArrayIterator
MultipleIterator__construct(int $flags = MultipleIterator::MIT_NEED_ALL), attachIterator(Iterator $iterator, string|int|null $info = null): void, detachIterator(Iterator $iterator): void, containsIterator(Iterator $iterator): bool, countIterators(): int, getFlags(): int, setFlags(int $flags): void, rewind(), valid(), key(), current(), next()
<?php
$it = new ArrayIterator(["a" => 10, "b" => 20]);
$it["c"] = 30;

foreach ($it as $key => $value) {
    echo $key;
    echo "=";
    echo $value;
    echo "\n";
}

$obj = new ArrayObject(["left" => 1, "right" => 2]);
foreach ($obj as $key => $value) {
    echo $key;
    echo $value;
}

$wrapped = new IteratorIterator($obj, "ArrayObject");
foreach ($wrapped as $key => $value) {
    echo $key;
    echo $value;
}

$limited = new LimitIterator(
    new InfiniteIterator(new ArrayIterator([1, 2])),
    0,
    5
);
foreach ($limited as $value) {
    echo $value; // 12121
}

function keep_large(int $value, string $key, Iterator $inner): bool {
    return $value > 1;
}

$filter = new CallbackFilterIterator(
    new ArrayIterator(["a" => 1, "b" => 2]),
    keep_large(...)
);
foreach ($filter as $key => $value) {
    echo $key;
    echo $value;
}

$regex = new RegexIterator(
    new ArrayIterator(["first" => "item-10", "second" => "skip"]),
    "/([a-z]+)-([0-9]+)/",
    RegexIterator::GET_MATCH
);
foreach ($regex as $key => $matches) {
    echo $key;
    echo $matches[1];
    echo $matches[2];
}

$cache = new CachingIterator(
    new ArrayIterator(["a" => "A", "b" => "B"]),
    CachingIterator::FULL_CACHE | CachingIterator::TOSTRING_USE_KEY
);
foreach ($cache as $key => $value) {
    echo (string) $cache;
    echo $cache->hasNext() ? "more" : "last";
}
echo $cache["a"];

$append = new AppendIterator();
$append->append(new ArrayIterator(["a" => 1]));
$append->append(new ArrayIterator(["b" => 2]));
foreach ($append as $key => $value) {
    echo $key;
    echo $value;
}

$multi = new MultipleIterator(
    MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_ASSOC
);
$multi->attachIterator(new ArrayIterator(["a" => 1, "b" => 2]), "left");
$multi->attachIterator(new ArrayIterator(["x" => 10]), "right");
foreach ($multi as $keys => $values) {
    echo $keys["left"];
    echo is_null($values["right"]) ? "missing" : $values["right"];
}

$tree = new RecursiveIteratorIterator(
    new RecursiveArrayIterator(["a" => ["x" => 1], "b" => 2]),
    RecursiveIteratorIterator::SELF_FIRST
);
foreach ($tree as $key => $value) {
    echo $tree->getDepth();
    echo ":";
    echo $key;
    echo "=";
    echo gettype($value) === "array" ? "array" : $value;
}

$regexTree = new RecursiveIteratorIterator(
    new RecursiveRegexIterator(
        new RecursiveArrayIterator(["keep" => ["apple" => 1], "drop" => ["pear" => 2]]),
        "/keep|apple/",
        RecursiveRegexIterator::MATCH,
        RecursiveRegexIterator::USE_KEY
    ),
    RecursiveIteratorIterator::SELF_FIRST
);
foreach ($regexTree as $key => $value) {
    echo $key;
}

$info = new SplFileInfo("notes/todo.txt");
echo $info->getFilename();
echo $info->getExtension();

$file = $info->openFile();
foreach ($file as $line => $text) {
    echo $line;
    echo trim($text);
}

$paths = new FilesystemIterator(
    "notes",
    FilesystemIterator::KEY_AS_FILENAME |
    FilesystemIterator::CURRENT_AS_PATHNAME |
    FilesystemIterator::SKIP_DOTS
);
foreach ($paths as $name => $path) {
    echo $name;
    echo $path;
}

IteratorIterator accepts PHP’s optional $class downcast argument. Direct Iterator inputs evaluate the argument and ignore it. IteratorAggregate inputs validate that the class string names the aggregate class or one of its concrete Traversable base classes before calling getIterator().

ArrayIterator and ArrayObject preserve insertion-order keys for array inputs and for writes through ArrayAccess. Appends use the current storage length as the next integer key. IteratorIterator accepts any Traversable; when passed an IteratorAggregate, it calls getIterator() once and wraps the returned iterator. LimitIterator, NoRewindIterator, and InfiniteIterator follow PHP’s constructors and require an Iterator directly.

FilterIterator is abstract and skips inner positions whose accept() returns false during rewind() and next(). CallbackFilterIterator stores a callable and invokes it with current value, current key, and the inner iterator object; closure and first-class-callable capture environments are preserved with the iterator object. Branch-shaped expressions that select captured callable descriptors at runtime use the same descriptor invoker path and keep the selected receiver/capture environment with the iterator. Callable-array variables and literals such as [$object, $method] and [$class, $method] can also be resolved at construction time and stored as persistent descriptor callback environments. RegexIterator filters by applying the stored regex to the current value, or to the key when USE_KEY is set. It supports MATCH, GET_MATCH, ALL_MATCHES, SPLIT, and REPLACE modes, INVERT_MATCH, mutable replacement, and the accessor/mutator methods listed above. Regex execution uses the same PCRE2-backed runtime as the preg_* functions documented in Regex. GET_MATCH supports PREG_OFFSET_CAPTURE; ALL_MATCHES supports PREG_SET_ORDER and PREG_OFFSET_CAPTURE; SPLIT supports PREG_SPLIT_NO_EMPTY, PREG_SPLIT_DELIM_CAPTURE, and PREG_SPLIT_OFFSET_CAPTURE. Capture materialization exposes the full match plus all compiled numbered capture groups; unmatched interior captures are empty strings and trailing unmatched groups are omitted. ALL_MATCHES stores every non-overlapping match collected for an element. CachingIterator implements one-element lookahead through hasNext(), supports the string mode flags CALL_TOSTRING, TOSTRING_USE_KEY, TOSTRING_USE_CURRENT, and TOSTRING_USE_INNER, and supports FULL_CACHE for getCache(), count(), and ArrayAccess. SplFileInfo delegates path components, stat data, permissions, and type predicates to the filesystem builtins documented in System and IO. getFileInfo(), getPathInfo(), and openFile() honor explicit class-string arguments and setInfoClass() / setFileClass() overrides when the selected class extends SplFileInfo or SplFileObject as required. SplFileObject snapshots file contents into line storage with file() for iteration, uses a live stream for byte-position methods such as fread(), fwrite(), fseek(), ftell(), and ftruncate(), reloads line storage after stream writes, supports basic CSV splitting, and exposes SplFileObject::DROP_NEW_LINE, READ_AHEAD, SKIP_EMPTY, and READ_CSV. SplTempFileObject exposes PHP-compatible logical stream names: negative maxMemory values report php://memory, while non-negative values report php://temp/maxmemory:N. Contents stay in memory until the configured maxMemory threshold is exceeded; after that the object spills to an internal temporary file while preserving the current stream position. DirectoryIterator snapshots scandir() results. FilesystemIterator applies SKIP_DOTS, key-mode, and current-mode flags over that snapshot, while GlobIterator snapshots glob() matches and implements Countable.

AppendIterator skips exhausted appended iterators and exposes the current storage key through getIteratorIndex(). Its getArrayIterator() result is a live ArrayIterator view: appending, keyed offsetSet(), and offsetUnset() through that view updates the owner. MultipleIterator supports PHP’s MIT_NEED_ANY, MIT_NEED_ALL, MIT_KEYS_NUMERIC, and MIT_KEYS_ASSOC flags. Re-attaching the same iterator updates its info instead of duplicating it. When associative-key mode is active, attaching an iterator with null info raises InvalidArgumentException when key() or current() materializes the composite arrays, matching PHP.

RecursiveArrayIterator detects nested arrays and nested RecursiveIterator objects through hasChildren(). RecursiveIteratorIterator supports LEAVES_ONLY, SELF_FIRST, and CHILD_FIRST; it keeps a live stack of source sub-iterators so getDepth(), getInnerIterator(), and getSubIterator() track the active cursors. RecursiveCallbackFilterIterator preserves closure and first-class-callable capture environments, including branch-selected descriptor environments and runtime-selected callable-array variables or literals, when it wraps child iterators. RecursiveRegexIterator wraps child iterators with the same pattern, mode, flags, preg flags, and replacement value. RecursiveDirectoryIterator wraps directory children with the same filesystem flags. RecursiveCachingIterator checks the cached current value for array or RecursiveIterator children and wraps children in another caching iterator. ParentIterator recursively keeps only entries that have children.

Autoload and Introspection

SPL autoload and class-introspection helpers are documented in Namespaces. This includes spl_autoload_register(), spl_autoload_unregister(), spl_autoload_functions(), spl_autoload_extensions(), spl_autoload_call(), spl_classes(), spl_object_id(), spl_object_hash(), class_implements(), class_parents(), and class_uses().

Iterator Helper Functions

The iterator helper functions cover the PHP SPL traversal helpers:

FunctionSignatureNotes
iterator_to_array()iterator_to_array(Traversable|array $iterator, bool $preserve_keys = true): arrayRewinds object iterators, collects current() values, and optionally preserves key() results
iterator_count()iterator_count(Traversable|array $iterator): intRewinds and advances object iterators until valid() is false
iterator_apply()iterator_apply(Traversable $iterator, callable $callback, ?array $args = null): intCalls the callback once per valid position, stops when it returns false, and returns the invocation count
<?php
class Range implements Iterator {
    private int $i = 0;

    public function rewind(): void { $this->i = 0; }
    public function valid(): bool { return $this->i < 3; }
    public function current(): int { return $this->i + 10; }
    public function key(): string { return "k" . $this->i; }
    public function next(): void { $this->i = $this->i + 1; }
}

$items = iterator_to_array(new Range());
echo iterator_count(new Range());

function tick(string $label): bool {
    echo $label;
    return true;
}

echo iterator_apply(new Range(), "tick", ["!"]);

AOT constraints: iterator_to_array() accepts literal or dynamic scalar preserve_keys values and applies PHP truthiness at runtime. iterator_apply() accepts statically known Traversable objects and runtime-dispatched Traversable or iterable values; if an iterable value is an array at runtime, the program aborts because PHP’s iterator_apply() signature requires Traversable. The third iterator_apply() argument may be omitted, null, a literal array, a dynamic indexed array value, or a dynamic associative array when the callback has a statically known signature, including userland variadic callbacks. If the call site has no single static callback signature, elephc can dispatch dynamic indexed or associative args by matching the runtime callable pointer against user functions and closure/FCC wrappers available in that codegen context, then applying the matched target’s parameter and return metadata. Runtime string callback names dispatch over user functions and supported builtin wrappers by case-insensitive name matching and then use the same metadata path. Branch-shaped callbacks that select captured closure or first-class-callable descriptors at runtime are invoked through the descriptor’s uniform invoker, so receiver/capture environments and associative callback args are preserved. Runtime-selected callable-array variables such as [$object, $method] and [$class, $method] are matched to public method descriptors before the loop and reused for each callback invocation. For variadic callbacks, named keys consumed by fixed parameters are not copied into ...$rest; remaining string keys keep their names, and remaining numeric keys are reindexed from zero. Literal arrays with expressions are evaluated once before iteration starts. Dynamic arrays passed to by-reference callback parameters use temporary reference cells, so callback writes do not mutate the source argument array.