Reputation: 9008
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?
Upvotes: 6
Views: 1802
Reputation: 1086
After some research, I've found:
loophp/iterators
library. It does the exact same thing we expect it to - keeps iteration results and returns them on second iteration.Hence, consider checking out https://github.com/loophp/iterators
Upvotes: 0
Reputation: 53543
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
Upvotes: 4