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

发布于 2024-11-18 03:46:21 字数 2042 浏览 1 评论 0原文

我正在尝试创建一个像 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'         
  )
...

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

有什么想法吗?

I'm trying to create a iterator like this one, for a list of comments:

// 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]);
  }
}

The comment iterator:

class MyCommentIterator extends MyIterator{

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

And this is how I use it:

$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; ?>

So everything is working fine, besides one thing: I can't figure it out how to process nested comments :(

The $comments array returns a flat list of comments, like:

[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'         
  )
...

I need to somehow be able to check for child comments (on multiple levels) and insert them before the </li>'s of their parent comments...

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伴我老 2024-11-25 03:46:21

递归是你的朋友。

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

这篇文章中出现的所有代码都是伪代码。任何与真实代码的相似之处,无论是有效的还是损坏的,都纯属巧合。

Recursion is your friend.

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

All code appearing in this post is pseudo. Any resemblance to real code, working or broken, is purely coincidental.

姐不稀罕 2024-11-25 03:46:21

您可能想查看 RecursiveIterator 接口 PHP手动。如果您使用该接口的方法扩展迭代器,则可以使用 RecursiveIteratorIterator PHP 手册 顺序。

然而,由于您的输出是一个平面列表,因此您需要自己处理级别的逻辑,例如在每个深度向上插入

    ,并在每个深度插入

每个深度。

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

You might want to look into the RecursiveIterator Interface PHP Manual. If you extend your iterator with the methods by that interface, you're able to iterate over your comments with an instance of RecursiveIteratorIterator PHP Manual sequentially.

However as your output is a flat list, you need to take care of the logic for the levels on your own, e.g. inserting <ol> per depth up, and </ol> per depth down.

Use the flags to control the order how children are traversed.

蘸点软妹酱 2024-11-25 03:46:21

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

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

/* 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()

干杯。

You are using a flat array, but in reality, the items of that array are a tree or hierarchical data structure.

You are basically displaying a sequential list. Maybe you should construct a tree / hierarchical data structure first, without displaying, and later display data from the tree list.

/* 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()

Cheers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文