嵌套while循环

时间:2011-08-11 03:56:48

标签: php while-loop

我有一个评论系统。每条评论都可能收到回复,每个回复都会收到回复,但令人作呕。

因此,我的数据库包含一个名为“comments”的表,其中包含以下重要字段:

id
text
reply_to

...在reply_to下,当然是评论的回复。

所以现在,问题很简单:如何显示所有评论,但知道每条评论后必须回复它,并且每次回复后必须回复回复等等?

我最努力的东西,以及我一直在回归的东西,是这样的:

$query = mysql_query("SELECT * FROM comments WHERE reply_to=0");
while ($comment = mysql_fetch_array($query))
    include("comment.php");

在comment.php中,我所拥有的是:

foreach ($comment as $key = $value) $$key = $value;
echo $text;
echo "<div style='margin-left:30px;'>"; //A margin for a little indent
$subquery = mysql_query("SELECT * FROM comments WHERE reply_to=$id");
while ($comment = mysql_fetch_array($subquery))
    include("comment.php");
echo "</div>";

但是,如果我正确地再现了我的代码的本质,问题是:在第一个回复被回应后,它继续第一个回复的第一个回复,然后是第一个回复的第一个回复第一个回复,但循环永远不会到达任何东西的第二个回复。例如,假设表有3条评论,每条评论有3条回复,每条评论都有3条回复等,上面的代码会输出:

Comment
  First reply
    First second-order reply
      First third-order reply
        ...

我希望我已经清楚地解释了它。 inb4:我无法在表中添加新列。

5 个答案:

答案 0 :(得分:2)

在伪代码中:

function display_comment(comm)
  echo comm's info and text
  children = get children of the comment: SELECT from comments WHERE parent = (comm's id)
  echo <div class="comment-thread">
  foreach children as child
    display_comment(comm) // notice this line
  echo </div>

你必须创建一个函数,以递归引用它。

答案 1 :(得分:0)

我通常这样做

  function get_comments($text_id, $parent_id,$depth){
         $sql="SELECT * FROM spam WHERE parent_id='".(int)$parent_id."' AND text_id='".(int)$text_id."' ";
         //..query 
         while ($row=mysql_fetch_assoc($query)){
             //some comment output use $depth*pixels to indent
             $depth++; 
             get_comments($text_id,$row['parent_id'],$depth);
             $depth--;

         }

  }

并在第一次通话中

  get_comments($text_id,0,0); //

答案 2 :(得分:0)

$subquery = mysql_query(SELECT * FROM comments WHERE reply_to=$comment_id);

可能有些错误。当您描述表格定义时,带有comment`s id的字段名为id,但您在此处使用的是comment_id。此外,您没有将SQL语句括在引号(' ')中。是复制粘贴相关的错误吗?

答案 3 :(得分:0)

嗯,有趣的东西。所以这是我的想法(这是一个设计问题,所以我猜有很多方法)。我个人而言,我会使用字典来表示家长评论。这里有一些关于我如何处理这个问题的伪代码:

首先是DB:

+--------------------------+
| comments                 |
+--------------------------+
| id (INT)                 | <-- a unique id for the comment
| post_id (INT)            | <-- the original post / article being replied to
| parent_id (INT)          | <-- the comment this is in response to
| commenter_email (VARCHAR)| <-- just some way to identify the commenter
| comment_text (TEXT)      | <-- the actual comment
+--------------------------+

第二个伪代码:

function print_comment($comment_id, $replies_children, $comments)
{
    // For every comment at this level...
    foreach($reply_id in $replies_children[$comment_id])
    {
        // Create a div container to contain both this comment AND
        // all child comments. We let CSS take care of indenting.
        echo '<div style="padding-left: 10px;">';

        // Print this comment first...
        echo $comments[$reply_id]['comment_text'];

        // And beneath it print all of the replies to this comment
        print_comment($reply_id, $replies_children, $comments);

        // Finally end this level of comment indentation
        echo '</div>';
    }
}

// Fetch all of the comments at once for post id 10
$sql = "SELECT * FROM comments WHERE post_id = 10;";

// Get the results back (associative array, please)
$results = execute_sql($sql);

// Holds a list of replies (comment ids) for each comment
$replies_children = array();

// Lets us map an ID to the actual full sql result
$comments = array();

foreach($result in $results)
{
    // Make sure there's a list for the parent
    if($replies_children doesnt have key $result['parent_id']))
        $replies_children[$results['parent_id']] = array();

    // Append this item to the parent's list
    $replies_children[$result['parent_id']][] = $result['id'];

    // Allows us to get to this result by id directly
    $comments[$result['id']] = $result;
}

// Assume that id = 0 is the root level
print_comment(0, $replies_children, $comments);

这样你只需要调用一次数据库。

答案 4 :(得分:0)

如果你还包括深度列,你的生活会更容易。

http://www.devx.com/tips/Tip/22127