Reputation: 153
I have a class in PHP with a private array field, and implement IteratorAggregate by walking over this array and yielding new values.
class Item implements IteratorAggregate{
private static $items = array(
'a' => array(1, 2);
'b' => array(3, 4);
'c' => array(5, 6);
);
public function getIterator() {
return array_walk(Item::$items, function ($value, $key) {
yield array('letter' => $key, 'number' => $value[0]);
});
}
}
I then try to pass a new instance of this class to a foreach
clause:
foreach((new Item()) as $value){
process($value);
}
However, this fails miserably:
Fatal error: Uncaught exception 'Exception' with message 'Objects returned by Item::getIterator() must be traversable or implement interface Iterator'
However, from my understanding, my class is traversable because it implements IteratorAggregate.
Any suggestions as to what I'm doing wrong? I could rewrite this to turn the yield into an array, but that doesn't explain why I'm getting the error that I'm getting.
Upvotes: 1
Views: 1293
Reputation: 41934
In your code, the yield
applies to the closure, not to the method. This means that the closure passed to array_walk
is a generator, getIterator
is now just a normal method that returns the return value of array_walk
(which is an array).
Simply use foreach
instead of array_walk
:
class Item implements IteratorAggregate{
private static $items = array(
'a' => array(1, 2),
'b' => array(3, 4),
'c' => array(5, 6),
);
public function getIterator() {
foreach (self::$items as $key => $value) {
yield array('letter' => $key, 'number' => $value[0]);
}
}
}
Upvotes: 4