2011-08-11 362 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); 

這樣,你只有一次取消對數據庫。