devnotes.

Generators and Iterators

Generators let you write functions that produce a sequence of values lazily, one at a time, without building the entire result in memory first — essential when processing very large datasets or infinite sequences.

function readLargeFile(string $path): Generator
{
    $handle = fopen($path, 'r');
    while (($line = fgets($handle)) !== false) {
        yield $line; // pauses here, resumes on the next iteration
    }
    fclose($handle);
}

foreach (readLargeFile('huge-log.txt') as $line) {
    echo $line; // processes one line at a time, memory stays constant
}

Compare this to file('huge-log.txt'), which loads the entire file into memory as an array — a generator instead loads only one line at a time, no matter how large the file is.

Generators can also yield key-value pairs and receive values sent back into them via yield used as an expression:

function counter(): Generator
{
    $total = 0;
    while (true) {
        $amount = yield $total;
        $total += $amount ?? 0;
    }
}

The Iterator interface (implement current(), key(), next(), rewind(), valid()) is the lower-level mechanism generators are built on, letting any custom class be looped over with foreach — useful for wrapping custom collection classes with domain-specific iteration logic.

PHP Generators and Iterators Explained | DevNotes