Skip to main content

Command Palette

Search for a command to run...

PHP Generators

Published
3 min readView as Markdown

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

  1. Memory Efficiency: Generators are memory efficient because they yield values one by one and only keep the current value in memory.
  2. Simplicity: Generators simplify the creation of iterators without the need to implement the Iterator interface.
  3. 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 simpleGenerator function yields the values 1, 2, and 3.
  • The foreach loop 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 xrange function yields numbers from $start to $end, incremented by $step.
  • The yield keyword 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 send method is used to send values back into the generator. The generator receives these values and continues execution.
  • The current method 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 readFileByLine generator 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.

More from this blog

Khang Nguyen

119 posts