PHP – What are generators?
In PHP, a generator allows you to write code that uses foreach
to iterate over a dataset without needing to load the entire array into memory. Loading an array into memory can exceed memory limits or require a significant amount of processing time to generate.
Generators, or generator functions, help address this issue because they don’t return everything in a single return
. Instead of return
, generator functions use the yield
statement.
Generator functions can return as many yield
statements as needed.
In essence, a generator is a function that contains the yield
statement instead of return
. When called for the first time, the function with yield
creates a generator class object.
Generator object
This object implements the Iterator
interface in the same way as a forward-only iterator object and provides methods that can be invoked to manipulate the state of the generator, including sending values to it and returning values from it.
Its structure is as follows:
Description / DescripciónGenerator implements Iterator { /* Métodos */ public current ( void ) : mixed public getReturn ( void ) : mixed public key ( void ) : mixed public next ( void ) : void public rewind ( void ) : void public send ( mixed $value ) : mixed public throw ( Throwable $exception ) : mixed public valid ( void ) : bool public __wakeup ( void ) : void }
When a generator function is called, it returns an object that can be iterated over. When iterating over that object (e.g., with a foreach
loop), PHP will call the generator function each time a value is needed and will save the generator’s state when it provides a value with yield
. This allows the state to be restored when the next value is required.
This explanation sets the foundation for understanding how generators work efficiently in PHP.
An example of php.net<?php function xrange($start, $limit, $step = 1) { if ($start < $limit) { if ($step <= 0) { throw new LogicException('Step tiene que ser +ve'); } for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step tiene que ser -ve'); } for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } } /* * Obsereve que tanto range() como xrange() producen la misma * salida a continuación. */ echo 'Números impares de una cifra de range(): '; foreach (range(1, 9, 2) as $number) { echo "$number "; } echo "\n"; echo 'Números impares de una cifra de xrange(): '; foreach (xrange(1, 9, 2) as $number) { echo "$number "; } ?>
In this example provided on php.net, the range
function is compared with a generator function xrange()
. As mentioned earlier, xrange
will use significantly less memory. According to the calculations, xrange(0,10000,1)
would use about 1 KB of memory, whereas range(0,10000,1)
would use 100 MB for the same amount of numbers.
This highlights the efficiency of generators when dealing with large data sets.
References
- Anterior: generadores en PHP
- Siguiente: excepciones predefinidas en PHP