GENERATORS — PHP
Today I learned about generators and decided to write about them. When you run your php script it takes a space in your RAM and most of the time we don’t even bother to look how much space it consumes. But there are times we reach the limits of php. Like arrays.
<?php
class ArrayMaker
{
public function arrayMaker()
{
$array = range(1,10000000);
var_dump($array);
}
}
$generator = new ArrayMaker();
$generator->arrayMaker();
When we run it we will receive an error;
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 536870920 bytes) in D:\www2\Laracast\PHP\Generators\ArrayMaker.php on line 8
The size of this array eats up our resources. So normally we can not use a huge array like this. But where are some ways.
We Can Use Generators
Generators will call the function when needed so we won’t use the same space as before. An example would be;
<?php
class ArrayMaker
{
public function arrayMakerWithGenerator(){
for ($i = 0; $i < 100000000; $i++) {
yield $i;
}
}
public function arrayMaker()
{
foreach ($this->arrayMakerWithGenerator() as $number) {
var_dump($number);
}
}
}
$generator = new ArrayMaker();
$generator->arrayMaker();
As you see the function will behave like an array. It has its unique functions like;
- next
- send
- current
- key
public function arrayMaker()
{
$number = $this->arrayMakerWithGenerator();
var_dump($number->current());
}
This will give the current item, so it will be 0, but we can use next;
public function arrayMaker()
{
$number = $this->arrayMakerWithGenerator();
$number->next();
var_dump($number->current());
}
You will see 1 with this approach.
public function arrayMakerWithGenerator(){
for ($i = 0; $i < 100000000; $i++) {
yield $i => $i + 100;
}
}
public function arrayMaker()
{
foreach ($this->arrayMakerWithGenerator() as $key => $value) {
var_dump('This is ' . $key . ' and value is ' . $value);
}
}
What you get is;
string(26) “This is 0 and value is 100”
string(26) “This is 1 and value is 101”
And we can send data back to generate function and manipulate this stream;
public function arrayMakerWithGenerator(){
for ($i = 0; $i < 100000000; $i++) {
$result = yield $i;
if($result === 'ok') {
return;
}
}
}
public function arrayMaker()
{
$gen = $this->arrayMakerWithGenerator();
foreach ($gen as $number) {
var_dump($number);
if($number == 3) {
$gen->send('ok');
}
}
}
What you will see is;
int(0)
int(1)
int(2)
int(3)
Basically this is generator. I didn’t use in any places so far but there is no harm in knowing it.