Generators in PHP
Before we begin, you should make sure you are familiar with the concept of iterations as this will give you a heads up and allow for easier understanding of this topic. You’ll need PHP 5 or newer in order to use iterators, but chances are good you’re already there since we’re up to PHP 7 alread.
So today, we’ll cover the best and easiest way to implement simple iterators. By using this method we will bypass the difficulties of the Iterator interface.
Wikipedia gives this definition of a generator: “A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values.” It just performs simple functions, but one big difference is that despite returning a value, it dissolves as much values as it could. Apparently it looks like a function when in fact it is not; instead it is more of an iterator.
In generators we use the yield keyword instead of the return keyword which is used in iterators. It similar to how return works but it returns value to the caller of that function. Where instead of removing the function from the stack, yield stores the state and will call the function again from the state it was in before. An interesting thing about this is that, generator is a void function that doesn’t return any value, although you could use return that would not return any value.
The PHP manual states that “When a generator function is called, it returns an object that can be iterated over.” This is the object of the nested class of the generator or encapsulated Generator class which complies the Iterator interface in the exact way a forward-only iterator object works. The same way an iterate object in PHP calls the generator every time it requires the value. The state is preserved as the generator yields so it continues from the same place where the next value is required.
<?php
function cooks() {
echo "Now the generator has started";
for ($i = 0; $i < 10; ++$i) {
yield $i;
echo "It has yielded $in";
}
echo "Now the generator has stopped ";
}
foreach (cooks() as $v);
The output of the above code will be:
The generator has started
It has yielded 0
It has yielded 1
It has yielded 2
It has yielded 3
It has yielded 4
Now the generator has stopped
Creating a new generator
Generators are not unique to PHP and in fact exist in many other programming languages including Python, C#, JavaScript, and Ruby on rails. They can be pinned point by using the yield keyword in the generator. To clear this concept up we will look at an example in python as well:
def initialLines(firstFile):
file = open(firstFile)
for line in file:
yield line
file.close()
for line in firstFiles('any_random_file'):
Now we will convert this example from Python to PHP:
<?php
function Initiallines($firstFile) {
$file = fopen($firstFile, 'r');
while (($line = fgets($file)) !== false) {
yield $line;
}
fclose($file);
}
foreach (Initiallines('any_random_file') as $line) {
}
This generator function will open a file and after that it will yield every line from the file according to the requirements. Every time the function calls the generator, it will start from the place it stopped before. It won’t start from the initial state as its state had been saved when the yield statement was executed. The system will read every line once after that and the generator function execution will complete.
Use of the Returning function keys in PHP
In PHP the iterators are comprised of the combination of both keys and values as a pair. Now we will see in our example that only a single value was returned so that the keys consist of number values and are taken that way default by the system. In case you need to return an associate pair, you can just change the yield statement and use the syntax from the array which will work just fine.
At this stage we will inject the values into the code
yield is a function that doesn’t only returns values; it accepts values passed to it directly, indirectly, and added or passed to it by reference. All of this can be accomplished by using the send()function present in the function that could be used to pass any sort of value to this function. Then after that the value that was passed as a parameter could be used in any way the user requires or to perform any other sort of operation as desired. This function sends the value to the generator as a result of the yield expression and continues execution.
<?php
function values() {
for ($i = 0; $i < 5; ++$i) {
$cmd = (yield $i);
if ($cmd == 'hold') {
return;
}
}
}
$gen = values();
foreach ($gen as $v) {
if ($v == 3) {
$gen->send('hold');
}
echo "{$v}n";
}
The output for this code will be:
0
1
2
3
Generators to save memory efficiently
Generators work efficiently for managing large amounts of data when you don’t want to provide all of the memory allocation and at the same time or you don’t know for sure that you need results for all those computations. This is because of the way results are managed. Using compression can be effective by allotting memory precisely for only the current executing result.
Take a hypothetical situation in which we make a file() function that will return all of the lines stored in a file consecutively as they are stored in an array. We can demonstrate it by running a regular benchmark for the file() and also for our demonstration file_lines() functions, each by using the exact same random 100 para text file produced using Lipsum, demonstrated that the file utilized 110 times greater memory as compared to the generator.
<?php
$m = Max_memory_utilization();
foreach (initialLines('file1.txt') as $l);
echo Max_memory_utilization () - $m, "n";
$m = Max_memory_utilization ();
foreach (file('file1.txt') as $l);
echo Max_memory_utilization () - $m, "n";
Conclusion
When PHP introduced Generators to the language, it gave a powerful tool to the developer. With it we can write iterators instantly and also save a lot of memory during the whole process. With the help of this tutorial, I hope you will now be able to easily utilize their potential in your programs.
If you looking for more PHP, check of our comparison of IDEs for PHP
or stop by the main site to compare the best PHP development tools.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment