如单用类名(NoRewindIterator),the manual has具体写法如下:
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() 永远不会被调用。
这也是有道理的,原因与相关问题中给出的相同:Why must I rewind IteratorIterator。 NoRewindIterator 从 IteratorIterator 和 不同 延伸到它的父类,getInnerIterator() 方法返回 Iterator 而不是 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();
}
}