2011-08-11 301 views
1

我有一个评论系统。每条评论可能会收到回复,每个回复可能会收到回复,令人生厌。循环嵌套

因此,我的数据库中包含名为“意见”具有以下重要领域表:

id 
text 
reply_to 

...下REPLY_TO,当然,去评论的ID,它是一个答复。

所以现在问题很简单:我如何显示所有评论,但知道在每个评论必须收到回复后,每个回复后都必须回复回复等内容?

我试过最什么,以及我继续回来的,是这样的:

$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:我无法在表中添加新列。

+4

您需要将代码打包到一个函数中,并进行递归。 http://stackoverflow.com/questions/2648968/what-is-a-recursive-function-in-php – mario

+1

如果没有其他的东西,去睡觉,并且在你醒来后的几个小时不要考虑代码。如果你一整天都对你这么做,**会离开一段时间。** –

+1

在循环中打一个数据库也不是一个好主意。 id在1个查询中获取所有相关注释,然后尝试使用循环/递归显示它们。 –

回答

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> 

你必须做一个功能,使之递归引用。

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); // 
+0

在循环中执行没有准备好的SQL语句真的不好主意。 – Timur

+0

我只发布了这个作为递归循环的例子,而不是sql。我以为他在清理存储在数据库中的ID之前清理它,并且应该是整数并且已经被清除。但改变了我的帖子 –

+1

SQL语句已经在循环中:)关于准备好的语句 - http://dev.mysql.com/doc/refman/5.5/en/sql-syntax-prepared-statements.html,http:// php .net/manual/en/mysqli.prepare.php – Timur

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

可能有些错误。当你描述你的表格定义时,带有评论ID的字段被命名为id,但在这里你使用的是comment_id。另外,您并未将SQL语句放在引号中(' ')。是复制粘贴相关的错误?

+0

是的,抱歉。现在纠正它... – Sophivorus

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); 

这样,你只有一次取消对数据库。