MOCKSTACKS
EN
Questions And Answers

More Tutorials









PHP Generators


Generators are useful when you need to generate a large collection to later iterate over. They're a simpler alternative to creating a class that implements an Iterator, which is often overkill.
For example, consider the below function.

function randomNumbers(int $length)
{
 $array = [];

 for ($i = 0; $i < $length; $i++) {
 $array[] = mt_rand(1, 10);
 }

 return $array;
}

All this function does is generates an array that's filled with random numbers. To use it, we might do randomNumbers(10), which will give us an array of 10 random numbers. What if we want to generate one million random numbers? randomNumbers(1000000) will do that for us, but at a cost of memory. One million integers stored in an array uses approximately 33 megabytes of memory.

$startMemory = memory_get_usage();
$randomNumbers = randomNumbers(1000000);
echo memory_get_usage() - $startMemory, ' bytes';

This is due to the entire one million random numbers being generated and returned at once, rather than one at a time. Generators are an easy way to solve this issue.

A yield statement is similar to a return statement, except that instead of stopping execution of the function and returning, yield instead returns a Generator object and pauses execution of the generator function.

Here is an example of the range function, written as a generator:

function gen_one_to_three() {
 for ($i = 1; $i <= 3; $i++) {
 // Note that $i is preserved between yields.
 yield $i;
 }
}

You can see that this function returns a Generator object by inspecting the output of var_dump:

var_dump(gen_one_to_three())
 # Outputs:
 class Generator (0) {
}

Yielding Values



The Generator object can then be iterated over like an array.

foreach (gen_one_to_three() as $value) {
 echo "$value\n";
}

Output

1
2
3

Yielding Values with Keys


In addition to yielding values, you can also yield key/value pairs.
function gen_one_to_three() {
 $keys = ["first", "second", "third"];
 for ($i = 1; $i <= 3; $i++) {
 // Note that $i is preserved between yields.
 yield $keys[$i - 1] => $i;
 }
}
foreach (gen_one_to_three() as $key => $value) {
 echo "$key: $value\n";
}

Output

first: 1
second: 2
third: 3

Reading a large file with a generator


One common use case for generators is reading a file from disk and iterating over its contents. Below is a class that allows you to iterate over a CSV file. The memory usage for this script is very predictable, and will not fluctuate depending on the size of the CSV file.

<?php
class CsvReader
{
 protected $file;
 public function __construct($filePath) {
 $this->file = fopen($filePath, 'r');
 }
 public function rows()
 {
 while (!feof($this->file)) {
 $row = fgetcsv($this->file, 4096);

 yield $row;
 }

 return;
 }
}
$csv = new CsvReader('/path/to/huge/csv/file.csv');
foreach ($csv->rows() as $row) {
 // Do something with the CSV row.
}


Conclusion

In this page (written and validated by ) you learned about PHP Generators . What's Next? If you are interested in completing PHP tutorial, your next topic will be learning about: PHP UTF 8.



Incorrect info or code snippet? We take very seriously the accuracy of the information provided on our website. We also make sure to test all snippets and examples provided for each section. If you find any incorrect information, please send us an email about the issue: mockstacks@gmail.com.


Share On:


Mockstacks was launched to help beginners learn programming languages; the site is optimized with no Ads as, Ads might slow down the performance. We also don't track any personal information; we also don't collect any kind of data unless the user provided us a corrected information. Almost all examples have been tested. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. By using Mockstacks.com, you agree to have read and accepted our terms of use, cookies and privacy policy.