Generators can return a value as well as yield

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.