想象一下具有无限回复结构的评论系统。像这样:
Comment
Reply to comment
Reply to reply to comment
Reply to reply to reply to comment
etc....
Reply to comment
Comment
Reply to comment
我正在尝试将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();
?
答案 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查询构建树。