Generators advanced
| Send values in | |
| Return from generator | |
| Yield from | |
| Keys |
Send values in
By default data flows one way from yield to the loop. Calling send pushes a value back into the paused generator where yield works as an expression.
The value passed to send becomes the result of the current yield, so the generator can react to the caller on every step.
function echoer(): Generator { $input = yield "ready"; while (true) { $input = yield "got " . $input; } } $gen = echoer(); $gen->rewind(); echo $gen->current(); $gen->send("hello"); echo $gen->current();
Return from generator
A generator can finish with a return value in addition to yielded items. The loop still ends normally and then getReturn reveals the final result.
This pattern fits totals, counts, and status codes computed while streaming values one by one.
function countUp(int $max): Generator { for ($i = 1; $i <= $max; $i++) { yield $i; } return $max * 10; } $gen = countUp(3); foreach ($gen as $n) { echo $n; } echo $gen->getReturn();
Yield from
Yield from delegates part of the work to another generator. Values flow through as if written inline, which keeps large sequences split into small readers.
The outer generator pauses while the inner one runs, then continues after the last inner value.
function inner(): Generator { yield 1; yield 2; } function outer(): Generator { yield 0; yield from inner(); yield 3; } foreach (outer() as $v) { echo $v; }
Keys
Generators can yield keys together with values, just like arrays. String keys name each item, which makes logs and mapped data easier to follow.
Functions like iterator to array preserve those keys, so downstream code can stay unchanged.
function pairs(): Generator { yield "a" => 1; yield "b" => 2; } foreach (pairs() as $k => $v) { echo $k; echo $v; } var_dump(iterator_to_array(pairs()));
Next: Fibers (PHP 8.1)
Article author: Arthur Isaev