Skip to content
Iterators and IteratorAggregate
step 1/5

Reading — step 1 of 5

Learn

~1 min readClosures and Iterators

PHP's foreach works with any object implementing Iterator or IteratorAggregate.

Manual Iterator — 5 methods:

class Range implements Iterator {
    private int $current;

    public function __construct(
        private readonly int $start,
        private readonly int $end,
    ) {
        $this->current = $start;
    }

    public function current(): int { return $this->current; }
    public function key(): int { return $this->current - $this->start; }
    public function next(): void { $this->current++; }
    public function rewind(): void { $this->current = $this->start; }
    public function valid(): bool { return $this->current < $this->end; }
}

foreach (new Range(1, 5) as $k => $v) {
    echo "$k: $v\n";
}

That's a lot of boilerplate. IteratorAggregate is simpler — return an iterator from getIterator():

class UserCollection implements IteratorAggregate {
    public function __construct(private array $users = []) {}

    public function getIterator(): Iterator {
        return new ArrayIterator($this->users);
    }
}

Or just return a generator:

class NumberStream implements IteratorAggregate {
    public function getIterator(): Generator {
        yield 1;
        yield 2;
        yield 3;
    }
}

Generators (yield) are PHP's cleanest way to make iterables — covered next.

The Countable interface — adds count() support:

class MyCollection implements Countable {
    public function count(): int { return count($this->items); }
}

echo count(new MyCollection());

ArrayAccess — make an object usable with []:

class Config implements ArrayAccess {
    private array $data = [];
    public function offsetExists($k): bool { return isset($this->data[$k]); }
    public function offsetGet($k): mixed { return $this->data[$k] ?? null; }
    public function offsetSet($k, $v): void { $this->data[$k] = $v; }
    public function offsetUnset($k): void { unset($this->data[$k]); }
}

$cfg = new Config();
$cfg['key'] = 'value';
echo $cfg['key'];

Mix-and-match: a class that implements IteratorAggregate + Countable + ArrayAccess looks just like a PHP array.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…