2011-08-11 13 views
1

私はコメントシステムを持っています。それぞれのコメントは返信を受け取ることがあり、各返信は広告の嫌がらせである返信を受け取ることがあります。入れ子のwhileループ

このように、私のデータベースは、以下の重要なフィールドと「コメント」という名前のテーブルが含まれます。

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

でもあれば、私はほとんど、と私はで帰ってくるが、このようなもので試してみました何

私は自分のコードの本質を正しく再現しました。問題はこれです。最初の返信がエコーされた後、最初の返信の最初の返信に続き、最初の返信の最初の返信が続きますが、ループは何の2番目の返事に決して行きません。したがって、たとえば、テーブルを想定すると、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

他に何もなければ、起床してから数時間コードについて考えないでください。あなたがこの一日中、あなたの頭を叩いてしまったのなら、しばらくの間、** away away。** –

+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ではなく、再帰的ループの例として掲示しました。私は彼がdbに格納されている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); 

はいくつかの間違いかもしれませ。あなたのテーブル定義を記述するとき、comment`s 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 
+--------------------------+ 

第2の疑似コード:あなたは一度だけ、データベースに中止

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

この方法。