【问题标题】:Hierarchy commenting system php层次评论系统php
【发布时间】:2011-12-05 13:32:22
【问题描述】:

我想做 discus/reddit/ 之类的评论系统,我的评论数据库中有一个“id_answer”(默认设置为 0)字段,当用户回答另一个评论时,该字段是父级的“id”评论。

我在一个数组中有线程的 cmets,但我不知道如何过滤每个循环以获得类似的东西:

评论 1 级($array[id_answer] 为 0)

------- 评论 lvl 2 ($array[id_answer] 是 id_of_level_one_comment)

--------------- 评论 lvl 3 ...

【问题讨论】:

标签: php mysql multidimensional-array nested-sets


【解决方案1】:

在您的数据库中使用三个字段;

  • “id”,对于每条评论都是唯一的
  • “parent_id”,为 0(顶级评论)或父评论的“id”
  • “thread_id”,即您评论的任何内容的 id

假设您想显示您的新闻文章的评论树,ID 为“123”

从 mysql 中选择时,选择具有此 thread_id 的所有内容:

SELECT id, parent FROM comments WHERE thread_id = 123

然后您应该预先解析您的数组以将子 cmets 提供给其父母,并使用递归显示来显示每个评论及其子列表。

例如:

// getting the comments from mysql, I'm obviously not bothering
//   to check the return value, but in your code you should do it
$result = mysqli_query("SELECT id, parent FROM comments WHERE thread_id = 123");

$comments = array();
while ($row = mysqli_fetch_array($result)) {
  $row['childs'] = array();
  $comments[$row['id']] = $row;
}

// This is the array you get after your mysql query
// Order is non important, I put the parents first here simply to make it clearer.
/*
$comments = array(
    // some top level (parent == 0)
    1 => array('id' => 1, 'parent' => 0, 'childs' => array()),
    5 => array('id' => 5, 'parent' => 0, 'childs' => array()),
    2 => array('id' => 2, 'parent' => 0, 'childs' => array()),
    10 => array('id' => 10, 'parent' => 0, 'childs' => array()),
    // and some childs
    3 => array('id' => 3, 'parent' => 1, 'childs' => array()),
    6 => array('id' => 6, 'parent' => 2, 'childs' => array()),
    4 => array('id' => 4, 'parent' => 2, 'childs' => array()),
    7 => array('id' => 7, 'parent' => 3, 'childs' => array()),
    8 => array('id' => 8, 'parent' => 7, 'childs' => array()),
    9 => array('id' => 9, 'parent' => 6, 'childs' => array()),
);
*/

// now loop your comments list, and everytime you find a child, push it 
//   into its parent
foreach ($comments as $k => &$v) {
  if ($v['parent'] != 0) {
    $comments[$v['parent']]['childs'][] =& $v;
  }
}
unset($v);

// delete the childs comments from the top level
foreach ($comments as $k => $v) {
  if ($v['parent'] != 0) {
    unset($comments[$k]);
  }
}

// now we display the comments list, this is a basic recursive function
function display_comments(array $comments, $level = 0) {
  foreach ($comments as $info) {
    echo str_repeat('-', $level + 1).' comment '.$info['id']."\n";
    if (!empty($info['childs'])) {
      display_comments($info['childs'], $level + 1);
    }
  }
}

display_comments($comments);

这给出以下结果:

- comment 1
-- comment 3
--- comment 7
---- comment 8
- comment 5
- comment 2
-- comment 6
--- comment 9
-- comment 4
- comment 10

我将 ORDER BY 之类的东西留给你,因为它不会造成任何问题。

【讨论】:

  • 仅供参考:您可以(但绝不能,只是一个提示)将前两个 foreach 减少为一个:stackoverflow.com/questions/7673044/…(子键 0 在您的代码中有 childs)。
  • @hakre:谢谢,我从我的示例数组开始,忘记了他可以在获取行时将注释 id 作为数组的键,编辑和简化了很多。但是,我仍然需要在之后的第二次 foreach 中取消设置,因为我无法保证该行最终会以何种顺序排在他的排序之后。
  • @Tahola:感谢 hakre 的评论,我在答案中编辑了代码,当前的代码应该更容易阅读
  • @Lepidosteus:如果您之前为该值设置了别名,您甚至可以取消设置,请参阅链接示例,这是一个不错的举措。
  • @Lepidosteus:只要 ID 排序为 0-n 并且 parentid 与第二个相同,这应该可以工作。否则,包含该元素的引用数组&$map[$id] 可以为任何订单完成这项工作。就像我想的那样。
猜你喜欢
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 2016-07-31
  • 2016-05-02
  • 1970-01-01
相关资源
最近更新 更多