嵌套的foreach与迭代器接口

Der*_*erk 6 php foreach iterator

<? foreach ($this->criteria as $key => $value): ?>
<li><?= $this->accommodationsLink($this->criteria, $key) ?></li>
<? endforeach ?>
Run Code Online (Sandbox Code Playgroud)

此代码会产生意外结果,因为只能看到一个链接.但是$ this->标准中有两个项目.

我探究了问题的原因.在functionsLink中,是另一个foreach循环,它在同一个标​​准对象上运行

foreach ($criteria as $key => $value) {
    $params[$key] = $value;
}
Run Code Online (Sandbox Code Playgroud)

$ this-> criteria和$ criteria是实现php Iterator接口的相同对象.是否有一种简单的方法让这个代码工作或嵌套的foreach循环不可能与php迭代器接口?

irc*_*ell 2

$iterator->reset()好吧,第二个 foreach 将在运行之前调用。因此,当第二个 foreach 到达迭代器的末尾时,内部指针已经位于数组的末尾......

会是这样的:

$it->reset();
while ($it->valid()) {
   $it->reset();
   while ($it->valid()) {
       //do something
       $it->next();
   }
   $it->next();
}
Run Code Online (Sandbox Code Playgroud)

$it->next()购买它到达外循环调用的时间,它已经无效了。因此next()调用将“失败”,并$it->valid()返回 false。

这不是迭代器的问题,而是您使用的逻辑的问题。如果你确实必须嵌套循环,那么将clone迭代器($subit = clone $it)放在内部循环中,这样你就不会干扰指针......

编辑:克隆示例:

$it->reset();
while ($it->valid()) {
   $bar = clone $it;
   $bar->reset();
   while ($bar->valid()) {
       //do something
       $bar->next();
   }
   $it->next();
}
Run Code Online (Sandbox Code Playgroud)

或者,使用 foreach (语义上等效):

foreach ($it as $key => $value) {
    $subit = clone $it;
    foreach ($subit as $k => $v) {
        //Do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 另一种方法是实现 [`IteratorAggregate`](http://www.php.net/manual/en/class.iteratoraggregate.php)。如果恰好实现迭代器的对象封装了大量数据,则克隆可能会占用大量内存。 (5认同)