Generators

PHP has a great mechanism to create iterators in a compact fashion. This type of iterator comes with some severe limitations; they are forward only and cannot be rewound. Indeed, even to simply start an iterator from the start, you must rebuild the generator. In essence, this is a forward-only iterator.

A function that uses the yield keyword instead of the return keyword. This will act in the same way as a return statement, but it will not stop the execution of that function. A generator function can yield data as many times as you please.

When you populate an array with values, those values must be stored in memory which can cause you to exceed your PHP memory limit or require a significant amount of processing time for the generator. When you put the logic in a generator function, that overhead does not exist. The generator function may merely yield as many results as it needs; there's no need to prepopulate an array first.

Here is a simple generator that will var_dump a string stating, the generator has started. The function will then generate the first five square numbers while also outputting their place in the series with var_dump . It will then finally indicate the generator has ended:

<?php 
function squaredNumbers() 
{ 
  var_dump("Generator starts."); 
  for ($i = 0; $i < 5; ++$i) { 
    var_dump($i . " in series."); 
    yield pow($i, 2); 
  } 
  var_dump("Generator ends."); 
} 
 
foreach (squaredNumbers() as $number) { 
  var_dump($number); 
} 

The second part of this script loops through this function and runs a var_dump string on each number. The output of this is as follows:

Generators

Let's amend this function slightly.

It is very important to note that if you add a return type to the variable, you can only declare a return type of Generator, Iterator or Traversable, integer.

Here is the code:

<?php 
function squaredNumbers(int $start, int $end): Generator 
{ 
  for ($i = $start; $i <= $end; ++$i) { 
    yield pow($i, 2); 
  } 
} 
 
foreach (squaredNumbers(1, 5) as $number) { 
  var_dump($number); 
} 

The result of this is as follows:

Generators

What if we want to yield a key as well as a value? Well, this is fairly easy.

There's something else to mention about generators to those who used them in PHP 5: in PHP 5, when you want to simultaneously yield a variable while setting it to a variable, you must wrap the yield statement in brackets. This restriction does not exist in PHP 7.

This works in PHP 5 and 7:

$data = (yield $value);

This only works in PHP 7:

$data = yield $value;

Let's suppose we want to amend our generator so that it yields a key-value result. Here's what the code looks like:

<?php 
 
function squaredNumbers(int $start, int $end): Generator 
{ 
  for ($i = $start; $i <= $end; ++$i) { 
    yield $i => pow($i, 2); 
  } 
} 
 
foreach (squaredNumbers(1, 5) as $key => $number) { 
  var_dump([$key, $number]); 
} 

When we test this, we will var_dump a two-dimensional array containing a key-value store of whatever the generator has yielded in a given iteration.

Here is the output:

Generators

Just a few other tips, a yield statement with no variable (like the one shown in the succeding command) will simply yield null:

yield;

You may also use yield from which will yield the inner values of any given generator.

Let's suppose we have an array of two values:

[1, 2] 

When we use yield from to yield an array of two values we get the inner values of the array. Let me demonstrate this:

<?php 
 
function innerGenerator() 
{ 
  yield from [1, 2]; 
} 
 
foreach (innerGenerator() as $number) { 
  var_dump($number); 
} 

This will display the following output:

Generators

However, now let's alter this script so that it uses yield instead of yield from:

<?php 
 
function innerGenerator() 
{ 
  yield [1, 2]; 
} 
 
foreach (innerGenerator() as $number) { 
  var_dump($number); 
} 

We will now see that instead of merely just the inner values of the array, we get the outer container too:

Generators

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.200.71