
Question:
I have a class Foo, I need to do :
$foo = new Foo();
foreach($foo as $value)
{
echo $value;
}
and define my own method to iterate with this object, exemple :
class Foo
{
private $bar = [1, 2, 3];
private $baz = [4, 5, 6];
function create_iterator()
{
//callback to the first creation of iterator for this object
$this->do_something_one_time();
}
function iterate()
{
//callback for each iteration in foreach
return $this->bar + $this->baz;
}
}
Can we do that? How?
Answer1:You need to implement the <a href="http://php.net/manual/fr/class.iterator.php" rel="nofollow">\Iterator</a> or <a href="http://php.net/manual/fr/class.iteratoraggregate.php" rel="nofollow">\IteratorAggregate</a> interface to achieve that.
A simple example of what you're trying to achieve using the \IteratorAggregate and \Iterator interfaces (I've left out the \Iterator implementation details, but you can use the PHP doc to see how they work) :
class FooIterator implements \Iterator
{
private $source = [];
public function __construct(array $source)
{
$this->source = $source;
// Do whatever else you need
}
public function current() { ... }
public function key() { ... }
public function next()
{
// This function is invoked on each step of the iteration
}
public function rewind() { ... }
public function valid() { ... }
}
class Foo implements \IteratorAggregate
{
private $bar = [1, 2, 3];
private $baz = [4, 5, 6];
public function getIterator()
{
return new FooIterator(array_merge($this->bar, $this->baz));
}
}
$foo = new Foo();
foreach ($foo as $value) {
echo $value;
}
Answer2:You need to implement the <a href="http://php.net/manual/en/class.iterator.php" rel="nofollow">Iterator</a> interface.
class Foo implements Iterator {
You should review the built in interfaces:
<a href="http://php.net/manual/en/reserved.interfaces.php" rel="nofollow">http://php.net/manual/en/reserved.interfaces.php</a>