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();
?>

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to