创建分层评论系统(使用PHP和MySQL有效[1表])

时间:2010-12-04 15:44:08

标签: php mysql

我想发表评论部分,回复评论。答复只会达到一个级别。例如。

家长评论

-- Here is a reply
-- Here is another reply
-- It won't go further than this one tier

我的MySQL看起来像这样:

  

comment_id,comment,parents_id

如果parents_id为0,则为父级。如果它有一个数字,那么这个数字将对应于comment_id,因为它将是它的孩子。

现在,我已经在下面完成了这个糟糕的代码,但似乎第二个循环使它变得混乱,只能正确地显示第一个div及其子代。我相信这是因为我两次调用mysql_fetch_row ...

$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);

for ($i = 0; $i < $num_rows_comments; $i++) {
    $comment = mysql_fetch_row($results_show_comments);
    echo "<p>comment_id: $comment[0]</p>";

    if ($comment[5] == 0) {
echo <<<_HTML
    <div class="dispArticle">
        <p><strong>Commenter Name commented @ 11/22/10 10:10:10pm</strong></p>
        <p>$comment[2]</p>
_HTML;

        for ($j = 0; $j < $num_rows_comments; $j++) {
            $replies = mysql_fetch_row($results_show_comments);
            if ($replies[5] > 0 AND $replies[5] == $comment[0]) {
echo <<<_HTML
        <div class="comment"><p><strong>Reply Name replied @ 11/22/10 10:10:10pm</strong></p>
            <p>child_id: $replies[0]</p>
            <p>parent_id: $comment[0]</p>
            <p>$replies[2]</p>
        </div>
        <br />
_HTML;
            }
        }
    }
echo "</div>";
}

一直在寻找几个小时,这就是我找到的。

  1. 使用多个表(希望将其保存在一个表中以减少查询)
  2. 使用多个查询(与上述相同)
  3. 首先输入一个数组,然后将其全部排序(如果注释很长并且有很多内容怎么办?我只是做了一个查询并且必须做更多的服务器端处理,将它提供给一个数组,排序然后显示。 ..)

3 个答案:

答案 0 :(得分:0)

问题是mysql_fetch_row()将始终获取查询返回的下一行,并且可以按任何顺序。对于您正在做的工作,您每次都需要立即跟踪其子评论。这是一个不稳定的解决方案,因此我建议您使用#3,因为它与您正在做的事情完全相同。

我还有一些建议:在mysql_fetch_row()上使用mysql_fetch_assoc()并使用列的名称而不是它们的数字,因为这使得代码更易读,更易于使用。您必须通过升序父ID更改查询以进行排序,以确保首先设置所有父项。然后:

$query = "query";
$result = mysql_query($query);
$comments = array();
while ($row = mysql_fetch_assoc($result)) {
   if ($row['parent_id']) {
      $comments[$row['parent_id']]['children'][] = $row;
   }
   else {
      $row['children'] = array();
      $comments[$row['comment_id']] = $row;
   }
}

现在所有的孩子都与父母联系在一起。只需遍历数组。

答案 1 :(得分:0)

这不是太难。您应该将所有注释存储在一个表中并拥有parent_id parent_id为0表示它是注释,parent_id&gt; 0将指向同一个表中的消息的id,它是一个回复。

你也会有article_id,就像你当前的例子一样。 你需要的技巧是只做一个SQL选择,但两次引用同一个表。

你的SQL会是这样的:

            SELECT
            M.id as id,
            M.id as com_mid,
            M.post_subject as com_subject,
            M.message_body as com_body,


            M2.id as rpl_mid,
            M2.post_subject as rpl_subject,
            M2.message_body as rpl_body,
            M2.parent_id


            FROM
            MESSAGES AS M
            LEFT JOIN MESSAGES as M2 on M2.parent_message_id = M.id

            WHERE M.article_id = :aid
            AND M.parent_id = 0
            ORDER BY com_mid ASC,
            rpl_mid ASC

然后,一旦你得到这个sql的结果,你将很容易弄清楚如何处理结果数组来显示消息和回复

答案 2 :(得分:0)

您需要第二个查询。以下是使用您的代码进行尝试的示例。

$query_show_comments = "SELECT * FROM article_comments WHERE article_id = '$article_id'";
$results_show_comments = mysql_query($query_show_comments);
$num_rows_comments = mysql_num_rows($results_show_comments);

for ($i = 0; $i < $num_rows_comments; $i++) {
    $row_comment = mysql_fetch_row($results_show_comments);
    echo "<p>comment_id: $row_comment[0]</p>";

    if ($row_comment[5] == 0) {
echo <<<_HTML
    <div class="dispArticle">
        <p><strong>Commenter Name commented @ 11/22/10 10:10:10pm</strong></p>
        <p>$row_comment[2]</p>
_HTML;

        $query_show_replies = "SELECT * FROM article_comments WHERE parent_id = '$article_id'";
        $result_replies = mysql_query($query_show_replies);
        while( $row_reply = mysql_fetch_row($results_show_comments) ) )
                echo "
                        <div class=\"comment\"><p><strong>Reply Name replied @ 11/22/10 10:10:10pm</strong></p>
                            <p>child_id: $row_reply[0]</p>
                            <p>parent_id: $row_reply[1]</p>
                        </div><br />
                ";
        }
    }
echo "</div>";
}

你在代码中做了几件我不喜欢做的事情,并不是说它不能那样做。我的建议是采用更先进的方法来构建您的Web应用程序:

  • 在从查询中读取数据时使用while()循环,它更容错“
  • 不要使用“echo&lt;&lt;&lt;”阻止因为它使代码更难阅读
  • 从技术上讲,您需要在网页的所有输出上使用htmlspecialchars,因此&lt;&lt;&lt;不应该使用
  • 更好的是,使用模板系统从PHP中解脱标记(视图),考虑Smarty,因为即使性能不是很好,它也很容易
  • 事实上,当您参与其中时,请考虑将您的数据代码抽象为separate layer
  • 无论您如何获取数据,在使用SELECT *时都不应该依赖索引字段,因为订单可能会发生变化。我的意思是,不是使用$comment[0]$comment[1],而是使用$comment['id']htmlspecialchars($comment['text'])