PHP Generators
Have you ever encountered this situation?
This is an error that any PHP developer might face if the running process uses more memory than the allowed limit.
Let’s go through a specific example:
private function range() { $a = []; for ($i = 0; $i < PHP_INT_MAX; $i++) { $a[] = $i; } return $a; } foreach ($this->range() as $value) { echo $value; }
This code will create an array from 0 to PHP_INT_MAX (the maximum integer value provided by the current PHP version) and print the values. When we run the code, we will encounter the memory overflow error mentioned earlier.
So how can we solve this issue if we happen to encounter it? One way is to increase the memory limit “memory_limit” in the php.ini config.
; Maximum amount of memory a script may consume ; https://php.net/memory-limit memory_limit = 128M
However, this is not the optimal solution. If such a small code causes a memory overflow, then it seems like something is not quite right. Instead of increasing the memory limit, let’s try using PHP Generators to reduce memory usage and see how effective it is!
What is PHP Generators?
PHP Generators are a powerful feature introduced in PHP 5.5. This feature allows you to create generator functions, which do not return the entire list of values at once. Instead, the function generates and returns each value only when needed. This significantly saves memory, allowing data to be processed without storing the entire dataset in memory.
Using PHP Generators
Going back to the code, let’s modify the “range()” function. Instead of creating an array (a list) and returning all the values in the array, we will loop through the values using the yield keyword. Simply put, yield will return a value, but only when we call it, without storing all values in memory like the initial code. This way, our function will become a generator function.
private function range() { for ($i = 0; $i < PHP_INT_MAX; $i++) { yield $i; } } foreach ($this->range() as $value) { echo $value; }
PHP Generators Methods
public current(): mixed public getReturn(): mixed public key(): mixed public next(): void public rewind(): void public send(mixed $value): mixed public throw(Throwable $exception): mixed public valid(): bool public __wakeup(): void
Working Example
Try another example:
function myGeneratorFunction() { echo 'One' . "<br>"; yield 'first return value' . "<br>"; echo 'Two' . "<br>"; yield 'second return value' . "<br>"; echo 'my return value' ; } $iterator = myGeneratorFunction(); $firstValue = $iterator->current(); echo $firstValue; $iterator->next(); $secondValue = $iterator->current(); echo $secondValue; $iterator->next(); echo $iterator->getReturn();
Output:
One first return value Two second return value my return value
Returning Keys
Using yield to return key ⇒ value
private function range() { for ($i = 0; $i < PHP_INT_MAX; $i++) { yield "key {$i}" => "value {$i}"; } } foreach ($this->rangeKeyValue() as $key => $value) { echo "{$key} -> {$value} <br>"; }
Output:
key 0 -> value 0 key 1 -> value 1 key 2 -> value 2 key 3 -> value 3 key 4 -> value 4 key 5 -> value 5 …
Passing Arguments into Generators
We can pass arguments into generators to perform actions such as stopping the function. Here’s how to do it:
private function range() { for ($i = 0; $i < PHP_INT_MAX; $i++) { $value = yield $i; if ($value === 'stop') { return; } } } $generator = $this->range(); foreach ($generator as $value) { if ($value === 5) { $generator->send('stop'); } echo "current value is {$value} <br>";
Output:
current value is 0 current value is 1 current value is 2 current value is 3 current value is 4 current value is 5
Benefits of Using PHP Generators
When our application needs to process a large log file, reading the entire file at once to process it could result in a memory overflow. Using PHP Generators to read one line at a time in the log file for processing can minimize memory usage and prevent system overloads.
Conclusion
For systems that need to handle large amounts of data, it’s crucial to consider and choose the best solution for efficiency and safety. PHP Generators provide a powerful solution to save memory and help keep our servers running smoothly and efficiently. It also helps avoid overload errors that could disrupt the system, negatively affecting user experience.
![]() | Huỳnh Hữu Phát Web Developer |