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.