就像单独的类名 ( NoRewindIterator
) 一样,该手册具体有以下措辞:
NoRewindIterator - 此迭代器不能倒带。
对于具体方法:
NoRewindIterator::rewind() - 防止内部迭代器的倒带操作。
这意味着该Iterator::rewind()
方法没有传递到内部迭代器。测试也表明了这一点,这是我一直在运行的一个简单的(不属于 PHP 的所有迭代器的代码都在Iterator Garden中):
$iterator = new RangeIterator(1, 1);
$debug = new DebugIteratorDecorator($iterator);
$noRewind = new NoRewindIterator($debug);
echo "first foreach:\n";
foreach ($noRewind as $value) {
echo "iteration value: $value\n";
}
在此代码中,调试迭代器即时打印(回显)迭代信息:
first foreach:
Iterating (RangeIterator): #0 valid()
Iterating (RangeIterator): #0 parent::valid() is TRUE
Iterating (RangeIterator): #0 current()
Iterating (RangeIterator): #0 parent::current() is 1
iteration value: 1
Iterating (RangeIterator): #1 next()
Iterating (RangeIterator): #1 after parent::next()
Iterating (RangeIterator): #1 valid()
Iterating (RangeIterator): #1 parent::valid() is FALSE
如上所示,$iterator->rewind()
从不调用。
出于相关问题中给出的相同原因,这也是有道理的:为什么我必须倒带 IteratorIterator。NoRewindIterator
扩展自它的父类IteratorIterator
并不同于它的父类,该getInnerIterator()
方法返回 anIterator
而不是 a Traversable
。
此更改允许您在需要时初始化倒带:
echo "\n\$calling noRewind->getInnerIterator()->rewind():\n";
$noRewind->getInnerIterator()->rewind();
echo "\nsecond foreach:\n";
foreach ($noRewind as $value) {
echo "iteration value: $value\n";
}
再次示例调试输出:
$calling noRewind->getInnerIterator()->rewind():
Iterating (RangeIterator): #0 rewind()
Iterating (RangeIterator): #0 after parent::rewind()
second foreach:
Iterating (RangeIterator): #0 valid()
Iterating (RangeIterator): #0 parent::valid() is TRUE
Iterating (RangeIterator): #0 current()
Iterating (RangeIterator): #0 parent::current() is 1
iteration value: 1
Iterating (RangeIterator): #1 next()
Iterating (RangeIterator): #1 after parent::next()
Iterating (RangeIterator): #1 valid()
Iterating (RangeIterator): #1 parent::valid() is FALSE
了解这些细节之后,就可以创建一个OneTimeRewindIterator
示例:
/**
* Class OneTimeRewindIterator
*/
class OneTimeRewindIterator extends NoRewindIterator
{
private $didRewind = FALSE;
public function rewind() {
if ($this->didRewind) return;
$this->didRewind = TRUE;
$this->getInnerIterator()->rewind();
}
}