A generator yields a sequence, and until PHP 7 that was all it could produce — so a function streaming rows had no way to also report how many it had streamed without a parameter by reference.
function export(iterable $rows): Generator
{
$n = 0;
foreach ($rows as $row) {
yield $row;
$n++;
}
return $n;
}
$gen = export($rows);
foreach ($gen as $row) { /* ... */ }
$written = $gen->getReturn();
getReturn() throws if called before the generator has finished, which is the rule that catches people — the value only exists once iteration has run to completion, so a break in the loop means there is no return value to collect. It pairs with yield from, where the delegated generator’s return value becomes the expression’s value.