我正在我的应用程序中构建一个嵌套的评论回复系统.
一切当前按预期工作,但我发现自己必须使用几个MySQL查询才能检索所需的数据.更糟糕的是,对'回复'的查询是在foreach循环中.这意味着虽然它现在表现令人钦佩,但它远非最佳,并且随着数据集的增长会引起问题.
因此,我希望在进一步深入发展之前解决这个问题.
由于该应用程序的表与该网站的wordpress博客共享相同,因此我使用wordpress简写进行查询.
生成页面的当前方式如下:
查询评论表并检索与项目相关的所有结果: -
$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);
Run Code Online (Sandbox Code Playgroud)
然后我执行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
}
}
Run Code Online (Sandbox Code Playgroud)
在这个循环中是另外两个查询.第一个得到每个评论的回复但是将结果限制为2(我希望这样做以便有一个"查看所有回复"按钮,然后如果用户需要,则查询数据库以获得其余的),第二个查询计数回复总数.
然后还使用上面循环中的第二个嵌套foreach(在这里生成html代码)为循环内的每个回复生成html,如下所示: -
if ($replies){
foreach ( $replies as $r ){
// generate each reply
}
}
Run Code Online (Sandbox Code Playgroud)
所有数据都以以下方式从这些数组中提取:
$c->userid, $c->body etc... For the comments
$r->userid, $r->body etc... For the replies.
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我希望保留这种格式.
正如在问题开头所述,这一切都完美无缺,但我知道通过嵌套回复和计数查询,我执行的查询比必要的要多得多.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";
Run Code Online (Sandbox Code Playgroud)
虽然这确实有用(并且足以让我将这个问题标记为已回答),但在实践中我遇到了一些困难.
首先,这将所有数据检索为单独的行,这意味着如果我有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;
}
Run Code Online (Sandbox Code Playgroud)
这样做可以根据需要为我提供嵌套数据对象.但是,它不包括回复计数查询,并且它不会按预期将每组回复限制为2,而是检索所有回复.
最后使用我在foreach循环中的当前html生成代码:
foreach($comments){
//generate comment html
foreach($replies) {
//generate replies html
}
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法让它与嵌套数据对象一起正常工作.访问正确的深层回复似乎让我感到困惑.
总而言之,我希望能够删除循环查询,将它们组合成一个更大,更高效的查询,或者最坏的情况是将数据查询和单独的计数查询组合在一起,然后创建一个整齐嵌套的数据对象,并将注释作为嵌套在"回复"标题下的行和任何回复
然后我需要能够在我的PHP代码中正确迭代这些以生成所需的html.
我为这个问题的长度道歉,并意识到它可能会让你们许多人不再回答,但我现在已经和你们争斗了19个小时,真的需要帮助.
非常感谢任何提出任何建议的人.
如果您想将评论和回复保留在两个不同的表中(请参阅 crafter 的评论),您可以使用一个简单的技巧来删除循环:从第一个查询中收集评论 ID 并使用
WHERE (cid IN (1,2,3,4,...))
而不是循环。如果您需要限制每个评论的回复,则可以使用附加的 WHERE- 或 HAVING 子句来实现。
伯宁利奥