In PHP 7.1 there is a new iterable psudo-type which abstracts arrays and Traversable
objects.
Suppose that in my code I have a class like the following:
class Foo
{
private $iterable;
public function __construct(iterable $iterable)
{
$this->iterable = $iterable;
}
public function firstMethod()
{
foreach ($this->iterable as $item) {...}
}
public function secondMethod()
{
foreach ($this->iterable as $item) {...}
}
}
This works fine is $iterable
is an array or an Iterator
, except when $iterable
is a Generator
. In that case in fact, calling firstMethod()
and then secondMethod()
would produce the following Exception: Cannot traverse an already closed generator
.
Is there a way to avoid this issue?
Generators can't be rewound. If you want to avoid this issue, you have to make a new generator. This can be done automatically if you create an object that implements IteratorAggregate:
class Iter implements IteratorAggregate
{
public function getIterator()
{
foreach ([1, 2, 3, 4, 5] as $i) {
yield $i;
}
}
}
Then just pass an instance of this object as your iterator:
$iter = new Iter();
$foo = new Foo($iter);
$foo->firstMethod();
$foo->secondMethod();
Output:
1
2
3
4
5
1
2
3
4
5