The following code attempts to use a class's iterator member with foreach.
This code will not run unless you comment out the offending foreach (marked
'** Comment out the next three lines...').
As demonstrated, it is possible to get() the iterator class and run it using
foreach() externally or to use it internally with a for() construct, but it
is not possible to use a foreach() construct internally when referencing
$this->my_iterator member.
Apologies for the squished up code:
<?php
//** Define an iterator
class MyIterator implements Iterator {
protected $arr = array('one' => 'ONE'
, 'two' => 'TWO'
, 'three' => 'THREE'
);
protected $position = 0;
function rewind()
{
reset($this->arr);
$this->position = 0;
}
function isValid() {
return $this->position < count($this->arr);
}
function hasMore() { //Only used with foreach()
return $this->isValid();
}
function hasNext() {
return $this->position < count($this->arr)-1;
}
function key()
{
return key($this->arr);
}
function current()
{
return current($this->arr);
}
function next()
{
next($this->arr);
$this->position++;
}
} //end class MyIterator
//** Test the iterator
$i = new MyIterator();
echo 'Starting iteration for $i... <br />';
foreach($i as $key => $value) {
echo $key .'<br />';
}
echo 'Ended iteration for $i... <br />';
//** Define a class which has an iterator member
class MyClass {
var $my_iterator;
function __construct($my_iterator) {
$this->my_iterator = $my_iterator;
}
function getMyIterator() {
return $this->my_iterator;
}
function doFor() {
echo 'Starting iteration for MyClass->doFor... <br />';
for( $this->my_iterator->rewind();
$this->my_iterator->hasMore(); //should be isValid() :)
$this->my_iterator->next()
) {
$key = $this->my_iterator->key();
echo $key . '<br />';
}
echo 'Ended iteration for MyClass->doFor. <br />';
}
function doForEach() {
echo 'Starting iteration for MyClass->doForEach... <br />';
//** Comment the next three lines to make this code run
foreach($this->my_iterator as $key => $value) {
echo $key . '<br />';
}
echo 'Ended iteration for MyClass->doForEach. <br />';
}
} //end class MyClass
//** Instantiate the class
$c = new MyClass($i);
//** Iterate by getting the iterator - OK
echo 'Starting iteration for $c->getMyIterator()... <br />';
foreach($c->getMyIterator() as $key => $value) {
echo $key .'<br />';
}
echo 'Ended iteration for $c->getMyIterator()... <br />';
//** Make the iterator run within the class (doFor) - SUCCESS
$c->doFor();
//** Make the iterator run within the class (doForEach) - FAILURE
$c->doForEach();
?
Please ignore - this has been fixed somewhere between php5-200402260830 and
php5-200403022230.
Philip