创建一个类似reddit的无限级评论回复系统

时间:2015-12-08 21:21:45

标签: php mysql comments

想象一下具有无限回复结构的评论系统。像这样:

Comment
  Reply to comment
    Reply to reply to comment
      Reply to reply to reply to comment
        etc....
  Reply to comment
Comment
  Reply to comment

像reddit一样:enter image description here

我正在尝试将PHP内部的结构与mysql结合起来做到这一点。我想到了这样的事情:

$query = mysqli_query($link, "SELECT * FROM comments");    
while($comment_array = mysqli_fetch_assoc($query)){
   echo $comment_array['text'];

   $query_reply = mysqli_query($link, "SELECT * FROM comments WHERE reply_id='$comment_array[id]'");
   while($reply_array = mysqli_fetch_assoc($query_reply)){
      echo $reply_array['text'];

      $query_reply2 = mysqli_query($link, "SELECT * FROM comments WHERE reply_id='$reply_array[id]'");
      while($reply_array2 = mysqli_fetch_assoc($query_reply2)){
         echo $reply_array['text'];

         ...... etc.
      }
   }
}

但是你可以看到这个结构存在问题。这种结构不是无限的,并且相同的代码必须重复很多次。

有没有办法更有效地做到这一点?把圈子放在某个地方?制作一个功能,如searchRepliesofComment();

2 个答案:

答案 0 :(得分:1)

您需要构建所谓的递归功能

function getComments($link, $parent = null) 
{
   $sql = "SELECT * FROM comments";
   $sql .= $parent ? " WHERE reply_id=".(int)$parent : null;
   $query = mysqli_query($link, $sql); 

   $results = array();
   while ($result = mysqli_fetch_assoc($query)) {
     if ($children = getComments($result['id'])) {
       $result['children'] = $children;
     }
     $results[] = $result;
   }
   return $results;
}

function renderComments(array $comments)
{
    $output = '';
    foreach ($comments as $comment) {
      $output .= $comment['text'];
      if (isset($comment['children'])) {
        $output .= renderComments($comment['children']);
      }
    }
    return $output;
}

现在您可以像以下一样呈现您的评论:

renderComments(getComments($link));

答案 1 :(得分:0)

有几种方法可以在没有未绑定递归的情况下处理此问题。即使对于读取,重复调用DB的递归函数也不是一个好主意。在测试环境中进行一些调用可能只需要几毫秒,但即使是一点点流量也可能会导致数据库陷入困境,因为每个请求都会触发大量的数据库命中。

第一个选项可以在所有回复中包含post_id,parent_reply_id。 post_id将允许选择适用于帖子但没有层次结构的所有回复。然后,您将使用parent_reply_id在内存中构建回复树。具有null parent_reply_id的回复将代表顶级回复。您可以使用“SELECT * FROM回复WHERE post_id =?ORDER BY parent_reply_id ASC”轻松构建此映射。以这种方式排序将使树真正地直接构建。

您还可以使用嵌套集模型。 Here就是一个很好的例子。当添加新的回复时,它确实会导致必须在许多回复上进行批量(但相对)轻量级写入操作的成本,但好处是您可以使用单个mysql查询构建树。

相关问题