PHP Generators
Introduction
Generators provide an easier way to iterate through data without building an array in memory. They allow you to write code that can be paused and resumed, producing values one at a time. This feature is particularly useful when dealing with large datasets or streams of data.
Key Features of Generators
- Memory Efficiency: Generators are memory efficient because they yield values one by one and only keep the current value in memory.
- Simplicity: Generators simplify the creation of iterators without the need to implement the
Iteratorinterface. - Lazy Evaluation: Generators yield values as they are requested, computing values on an as-needed basis.
Basic Usage
Here is a basic example of a generator function that yields values:
function simpleGenerator() {
yield 1;
yield 2;
yield 3;
}
foreach (simpleGenerator() as $value) {
echo $value, PHP_EOL; // Outputs: 1 2 3
}
In this example:
- The
simpleGeneratorfunction yields the values1,2, and3. - The
foreachloop iterates over these values, printing them out one by one.
Range Generator Example
A range generator is a common use case, providing a memory-efficient way to create a range of numbers:
function xrange($start, $end, $step = 1) {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}
foreach (xrange(1, 10) as $number) {
echo $number, PHP_EOL; // Outputs numbers from 1 to 10
}
In this example:
- The
xrangefunction yields numbers from$startto$end, incremented by$step. - The
yieldkeyword pauses the function, returning the current value and resuming from where it left off when the next value is requested.
Sending Values to Generators
Generators can also accept values sent from the outside using the send method:
function generator() {
$value = yield 'first';
echo $value, PHP_EOL; // Outputs: second
$value = yield 'third';
echo $value, PHP_EOL; // Outputs: fourth
}
$gen = generator();
echo $gen->current(), PHP_EOL; // Outputs: first
echo $gen->send('second'), PHP_EOL; // Outputs: third
echo $gen->send('fourth'), PHP_EOL; // No output, generator is done
In this example:
- The
sendmethod is used to send values back into the generator. The generator receives these values and continues execution. - The
currentmethod returns the yielded value at the current position.
File Processing Example
Generators are useful for processing large files, allowing you to read and process lines one at a time:
function readFileByLine($filePath) {
$handle = fopen($filePath, 'r');
if (!$handle) {
throw new Exception("Could not open the file!");
}
while (($line = fgets($handle)) !== false) {
yield $line;
}
fclose($handle);
}
foreach (readFileByLine('largefile.txt') as $line) {
echo $line;
}
In this example:
- The
readFileByLinegenerator reads a file line by line, yielding each line. - This approach is memory efficient, especially for large files, as it processes one line at a time.
Summary
Generators in PHP provide a powerful and memory-efficient way to create iterators. They are particularly useful when dealing with large datasets or streams of data. The yield keyword allows functions to pause and resume, producing values one at a time as needed. This lazy evaluation ensures that only the necessary data is in memory at any given time, making generators an excellent tool for optimizing performance and resource usage in PHP applications.