Be careful when caching the iterator AND supplying the iterator with a back reference to the IteratorAggregate implementor. This can cause a potential memory leak.
<?php
class MyClass implements IteratorAggregate {
public $data;
protected $iterator;
public function getIterator() {
return $this->iterator ? $this->iterator : $this->iterator = new MyIterator($this);
}
public function __construct($data) {
print "CONSTRUCTING MyClass!\n";
$this->data = $data;
}
public function __destruct() {
print "DESTROYING MyClass!\n";
}
}
class MyIterator implements Iterator {
protected $obj;
public function __construct($obj) {
print "CONSTRUCTING MyIterator!\n";
$this->obj = $obj;
}
public function current() { return current($this->obj->data); }
public function key() { return key($this->obj->data); }
public function next() { return next($this->obj->data); }
public function rewind() { return reset($this->obj->data); }
public function valid() { return key($this->obj->data) !== NULL; }
public function __destruct() {
print "DESTROYING MyIterator!\n";
}
}
function test1() {
$a = new MyClass(array(1, 2, 3, 4));
foreach ($a as $k => $v) {
print "$k => $v\n";
}
print "Iteration done!\n";
}
test1();
print "test1 done\n";
?>
Expected result
--------------------
CONSTRUCTING MyClass!
CONSTRUCTING MyIterator!
0 => 1
1 => 2
2 => 3
3 => 4
DESTROYING MyIterator!
Iteration done!
DESTROYING MyClass!
test1 done
Actual result
--------------------
CONSTRUCTING MyClass!
CONSTRUCTING MyIterator!
0 => 1
1 => 2
2 => 3
3 => 4
Iteration done!
test1 done
DESTROYING MyClass!
DESTROYING MyIterator!