# PHP Generators
A highly opinionated PHP generator cheat sheet:
# General
In PHP ~5.5, a function containing yield
becomes an instance of the
Generator
class, which acts like an iterator.
Each yield
occurence marks a position. Calling next
will move from the current yield to the next one.
Thanks to the send
method, the Generator
class acts also as a corroutine: you can send the returned value of the
yield
occurence.
A Generator
function cannot return a value.
# Generator class
class Generator
{
public function current(); // The yielded value.
public function key();
public function valid(); // Has the iterator been closed?
public function next(); // Resumes execution.
public function rewind();
public function send($value); // Sends the value to be returned by the current yield, and resumes execution.
public function throw(Exception $e); // Replaces the current yield with `throw $e;`
}
# Links to use cases
- co-routines as an alternative to state machines
- Cooperative multitasking using co-routines in PHP
- Python generators and co-routines
- What generators can do for you
# Examples
# Simple example
function direct_generator()
{
yield 1;
yield 'index' => 2;
}
$generator = direct_generator();
echo $generator->current(); // outputs 1
$generator->next();
echo $generator->current(); // outputs 2
echo $generator->key(); // outputs index
# Range example
Foreach internally calls current
, key
, next
and valid
methods.
function xrange($start, $end)
{
$value = $start;
while ($value <= $end) {
yield $value;
$value++;
}
}
foreach(xrange(1, 2) as $value) {
echo $value; // outputs 1, then 2.
}
# Co-routine example
Calling the send
method is like replacing the current yield
with the given value.
function holy_grail_countdown($number)
{
while (0 < $number) {
$reset = (yield $number);
$number = $reset ?: $number - 1;
}
}
$c = holy_grail_countdown(5);
foreach ($c as $number) {
echo "$number\n"; // outputs 5, then 2 and finally 1.
if (5 === $number) {
$c->send(3);
}
}