我正在我的应用程序中构建一个嵌套的评论回复系统。
当前一切都按预期工作,但是我发现自己必须使用多个MySQL查询才能检索所需的数据。更糟糕的是,对“答复”的查询在foreach循环内。这意味着,尽管它目前表现出色,但远非最佳,并且随着数据集的增长而引起问题。
因此,在进一步发展之前,我希望解决此问题。
由于该应用程序的表格与该网站的wordpress博客共享相同的内容,因此我使用wordpress速记进行查询。
当前生成页面的方式如下:
查询注释表,并检索与projectid相关的所有结果:-
$commentquery = "select projects_comments.*, users.user_url, users.display_name
from ".$wpdb->prefix."projects_comments projects_comments
left join ".$wpdb->prefix."users users on users.ID=projects_comments.userid
where projectid = '$projectid'
order by projects_comments.commentid desc
";
$comments = $wpdb->get_results($commentquery);
然后,我执行如下的foreach循环:
if($comments) {
foreach ( $comments as $c )
{
$replyquery = "select project_replies.*, users.user_url, users.display_name
from ".$wpdb->prefix."project_replies project_replies
left join ".$wpdb->prefix."users users on users.ID=project_replies.uid
where project_replies.cid = '$c->commentid'
order by project_replies.id desc
limit 2
";
$replies = $wpdb->get_results($replyquery);
asort($replies);
$countquery = "select count(*)
from ".$wpdb->prefix."project_replies project_replies
where project_replies.cid='".$c->commentid."'
";
$replycount = $wpdb->get_var($countquery);
//generate html here
}
}
在此循环内还有另外两个查询。第一个获取每个评论的答复,但将结果限制为2(我希望这样做是为了有一个“查看所有答复”按钮,然后如果用户需要,则向DB查询其余的消息),第二个查询答复总数。
然后,还使用上述循环中的第二个嵌套的foreach为循环中的每个答复生成html(它在此处表示生成html代码),如下所示:-
if ($replies){
foreach ( $replies as $r ){
// generate each reply
}
}
通过以下方式从这些数组中提取所有数据:
$c->userid, $c->body etc... For the comments
$r->userid, $r->body etc... For the replies.
我希望尽可能保留这种格式。
因此,正如问题开头所述,这一切都很好,但是我知道,通过嵌套答复和计数查询,我执行的查询比必要的多得多。 100条评论将生成100条回复查询和100条计数回复查询等。
感谢该站点上的一些乐于助人的人,我考虑使用联接一次性获得所有原始数据以进行评论和回复。像这样
$commentquery2 = "SELECT c.commentid, c.userid, c.body as cbody, c.projectid, c.posttime, cu.user_url AS cu_url, cu.display_name AS cu_name,
r.*, ru.user_url AS ru_url, ru.display_name AS ru_name
FROM ".$wpdb->prefix."projects_comments AS c
LEFT JOIN ".$wpdb->prefix."users AS cu ON cu.ID = c.userid
LEFT JOIN ".$wpdb->prefix."project_replies AS r ON r.cid = c.commentid
LEFT JOIN ".$wpdb->prefix."users AS ru ON ru.ID = r.uid
WHERE c.projectid = $projectid
ORDER BY c.commentid DESC, r.id DESC";
尽管这确实有效(并且足以让我将该问题标记为已回答),但在付诸实践时,我遇到了一些困难。
首先,这会将所有数据检索为单独的行,这意味着如果我有5条评论,每条评论有3条回复,我实际上会返回15行,而不是嵌套在每个评论行中的嵌套数据对象。
为了解决这个问题,我尝试了一些数组操作,如下所示:
$old_id=NULL;
$comments=array();
foreach($getcomments as $c){
if($c->commentid !== $old_id){
$comments[$old_id] = $c;
$old_id = $c->commentid;
}
$comments[$old_id]['replies'][] = $c;
}
这样做使我可以根据需要嵌套一个数据对象。但是,它不包括答复计数查询,并且没有按预期将每组答复限制为2,而是检索所有答复。
最后,在foreach循环中使用我当前的html生成代码:
foreach($comments){
//generate comment html
foreach($replies) {
//generate replies html
}
}
我似乎无法使它与嵌套数据对象一起正常工作。访问正确的深层答复似乎让我感到困惑。
因此,总而言之,我希望能够删除循环查询,将它们组合为一个大型高效的查询,或者在最坏的情况下将其合并为一个数据查询和一个单独的计数查询,然后创建一个整齐嵌套的数据对象,并将注释作为行和嵌套在“回复”标题下的所有回复
然后,我需要能够在我的php代码中正确地遍历这些内容,以便生成所需的html。
对于这个问题的冗长时间,我深表歉意,并意识到这很可能使许多人无法回答。但是,我已经连续19个小时与这个问题作斗争,确实需要帮助。
非常感谢任何提供建议的人。
最佳答案
如果您希望将评论和回复保留在两个不同的表中(请参阅手工艺者的评论),则可以通过以下简单的技巧来删除循环:从第一个查询中收集评论ID,然后使用
位置(cid IN(1,2,3,4,...))
而不是循环。如果您需要限制每个评论的回复数,则可以使用其他WHERE-或HAVING子句来实现。
伯恩·里奥