在PHP中实现多级“迭代器”

时间:2011-07-04 12:16:00

标签: php oop class iterator nested-loops

我正在尝试创建一个像this one这样的迭代器,以获取注释列表:

// the iterator class, pretty much the same as the one from the php docs...
abstract class MyIterator implements Iterator{

  public $position = 0,
         $list;

  public function __construct($list) {
    $this->list = $list;
    $this->position = 0;
  }

  public function rewind() {
    $this->position = 0;
  }

  public function current() {
    return $this->list[$this->position];
  }

  public function key() {
    return $this->position;
  }

  public function next() {
    ++$this->position;
  }

  public function valid() {
    return isset($this->list[$this->position]);
  }
}

评论迭代器:

class MyCommentIterator extends MyIterator{

  public function current(){
    return new Comment($this->list[$this->position]);
  }    
}

这就是我使用它的方式:

$comments = GetComments(); // gets the comments from the db
if($comments): ?>

  <ol>
    <?php foreach(new MyCommentIterator($comments) as $comment): ?>
    <li>
      <p class="author"><?php echo $comment->author(); ?></p>

      <div class="content">
        <?php echo $comment->content(); ?>
      </div>

      <!-- check for child comments and display them -->

    </li>
    <?php endforeach; ?>
  </ol>

<?php endif; ?>

所以一切都运行正常,除了一件事:我无法弄明白如何处理嵌套的评论:(

$comments数组返回一个平面的注释列表,如:

[0] => object(
    'id' => 346,
    'parent' => 0,  // top level comment
    'author' => 'John',
    'content' => 'bla bla'         
  ),

[1] => object(
    'id' => 478,
    'parent' => 346,  // child comment of the comment with id =346
    'author' => 'John',
    'content' => 'bla bla'         
  )
...

我需要能够以某种方式检查子评论(在多个级别上)并在父评论的</li>之前插入它们......

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

递归是你的朋友。

displaycomment(comment):
    $html .= "<ol>" . comment->html;
    foreach comment->child:
        $html .= "<li>" . displaycomment(child) . "</li>";
    $html .= "</ol>";
    return $html;

这篇文章中出现的所有代码都是伪的。任何与真实代码,工作或破坏的相似之处纯属巧合。

答案 1 :(得分:3)

您可能需要查看RecursiveIterator Interface PHP Manual 。如果使用该接口的方法扩展迭代器,则可以依次使用RecursiveIteratorIterator PHP Manual 的实例迭代注释。

但是,由于您的输出是一个平面列表,您需要自己处理关卡的逻辑,例如:每深度插入<ol>,每深度插入</ol>

使用标志来控制遍历子项的顺序。

答案 2 :(得分:1)

您正在使用平面数组,但实际上,该数组的项目是树或分层数据结构。

您基本上是显示顺序列表。也许你应该首先构建一个树/分层数据结构,不显示,然后再显示树列表中的数据。

/* array */ function FlatArrayToTreeArray(/* array */ $MyFlatArray)
{
  ...
}

/* void */ function IterateTree(/* array */ $MyTreeArray)
{
  ...
}

/* void */ function Example() {
  $MyFlatArray = Array(
  0 => object(
      'id' => 346,
      'parent' => 0,  // top level comment
      'author' => 'John',
      'title' => 'Your restaurant food its too spicy',
      'content' => 'bla bla'         
    ),
  1 => object(
      'id' => 478,
      'parent' => 346,  // child comment of the comment with id =346
      'author' => 'Mike',
      'title' => 'Re: Your restaurant food its too spicy',
      'content' => 'bla bla'         
    ),  
  2 => object(
      'id' => 479,
      'parent' => 478,  // child comment of the comment with id =346
      'author' => 'John',
      'title' => 'Re: Your restaurant food its too spicy',
      'content' => 'bla bla'         
    ),  
  3 => object(
      'id' => 479,
      'parent' => 346,  // child comment of the comment with id =346
      'author' => 'Jane',
      'title' => 'Re: Your restaurant food its too spicy',
      'content' => 'bla bla'         
    )
  );

  $MyTreeArray = FlatArrayToTreeArray($myflatarray);

  IterateTree($MyTreeArray);
} // function Example()

干杯。