2009-08-11 24 views
9

私はかなり長い間このことについて考えてきましたが、データベースのコメントに返信を追加する方法が必要ですが、どのように進めるのかは分かりません。コメントとコメントの返信のためのmysql構造

これは私の現在(あまり言いませんが、そのスタート)テーブルコメント:

SELECT c.id, c.comment, c.user_id, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
WHERE c.topic_id = 9 

一つのオプションは、作成するために次のようになります。

CREATE TABLE IF NOT EXISTS `comments` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ; 

、ここでは私の現在のクエリです"comment_replies"という新しいテーブルがありますが、わかりません。1つのクエリですべてのコメントとコメントの回答を選択できる場合、 "reply"という新しい列を追加すると、どのように並べ替えるか分かりませんそれぞれの返信でそれぞれのコメントを取得します。

私はこれに対処する方法についていくつかアドバイスを受けたいと思います。

編集:以下の1件のコメントから、アレイのこの種のparent_comment_id結果の追加についての答えと2件の回答後

:私はそれで動作するように、この配列をどのように処理すべきか

array(2) { 
    [0]=> 
    object(stdClass)#17 (7) { 
    ["id"]=> 
    string(2) "26" 
    ["comment"]=> 
    string(36) "adding a comment from the admin page" 
    ["user_id"]=> 
    string(2) "16" 
    ["ts"]=> 
    string(10) "1249869350" 
    ["username"]=> 
    string(5) "Admin" 
    ["photo"]=> 
    string(13) "gravatar2.png" 
    ["reply"]=> 
    string(23) "There is no admin page!" 
    } 
    [1]=> 
    object(stdClass)#18 (7) { 
    ["id"]=> 
    string(2) "26" 
    ["comment"]=> 
    string(36) "adding a comment from the admin page" 
    ["user_id"]=> 
    string(2) "16" 
    ["ts"]=> 
    string(10) "1249869350" 
    ["username"]=> 
    string(5) "Admin" 
    ["photo"]=> 
    string(13) "gravatar2.png" 
    ["reply"]=> 
    string(13) "Yes there is!" 
    } 
} 

、コメントを返信から分離することは可能ですか?

答えて

3

私はデータベースにparent_id列を追加することにしました。返信に参加するのではなく、すべてのコメントをすぐに後で選択して、コメントと返信をサーバーに並べ替えました側のコード、相続人の問い合わせ:すべての応答がコメントアレイ内のアレイとして追加されるように

SELECT c.*, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
WHERE c.topic_id = 9 
ORDER BY c.id ASC 

今私は基本的には、多次元配列を返し、以下の機能にクエリ結果を渡します。

function sort_comments($ar) 
{ 
    $comments = array(); 
    foreach($ar as $item) 
    { 
     if(is_null($item['parent_id'])) $comments[] = $item; 
     else 
     { 
      $parent_array = array_search_key($item['parent_id'],$comments,'id'); 
      if($parent_array !== false) $comments[$parent_array]['replies'][] = $item; 
     } 
    } 
    return $comments; 
} 
+3

関数 'array_search_key'とは何ですか?PHPの標準ライブラリ関数ではありません – HorusKol

+0

ページ分割はどのように機能しますか? – Mrusful

+0

ここで、array_search_key関数は何ですか?それはPHPに存在しますか? –

1

コメントの返信は、親のcomment_idのコメントです。 comment_idをフィールドとしてコメントテーブルに追加してみてください。あなたが得るのは木のような構造です。

コメントツリー全体を取得する場合は、ネストされたセット(https://wiki.htc.lan/Hierarchy_model)を使用することをお勧めします。しかしそれはもっと複雑な解決策です。

ここのMySQLからいくつかの詳細情報です:http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

あなたのコメントテーブルにparent_comment_id列を追加します。オプションにしてください。クエリを実行すると、すべての子コメントを各親に参加させることができます。選択的な非正規化(わずかな冗長性)のビットとして、子コメントにもtopic_idが設定されていることを確認することができます(すべての子コメントをメインコメントスレッドに表示することを前提としていますより小さいajaxリクエストを介して)。

プレゼンテーションをビルドする必要がありますが、結果をmemcached(またはフラットファイルまたはメモリ...キャッシュしていますが)に投げれば設定されます。

4

返信に返信できるようにする(例:オンラインメッセージフォーラムに表示されるような返信の階層を持つ)場合は、オプションのparent_comment_idフィールドをコメントテーブルに追加します。

あなたのテーブルには、すべてのコメントと返信を示すあなたのクエリがようなものになるだろう。この

`CREATE TABLE IF NOT EXISTS `comments` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `parent_comment_id` int(12) NULL, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ;` 

次のようになります。

SELECT c.id, c.comment, r.comment as reply, c.user_id, u.username, u.photo 
FROM (comments c) 
JOIN users u ON c.user_id = u.id 
LEFT JOIN comments r ON c.id = r.parent_comment_id 
WHERE c.topic_id = 9 

注しかし、このクエリを使用しての返信もないだけ現れるだろうと'reply'カラムだけでなく、 'comment'カラムにも0行以上の追加の行が追加されています。

コメントに返信したユーザーのユーザー名を表示するには、元のコメントを投稿したユーザーは最初にユーザーテーブルに2回参加し、返信ユーザーはもう一度参加する必要があります。答えたユーザーのユーザー名を表示するには、この文字列で検索してください:あなたは、ワードプレスでの作業parent_comment_idはなく、この場合、理想的なソリューションになっていたものと思わ追加されているよう

SELECT c.id, c.comment, c.user_id, u.username, u.photo, r.comment as reply, r.user_id as reply_user_id, 
u2.username as reply_username, u2.photo as reply_photo 
FROM (comment c) 
JOIN users u ON c.user_id = u.id 
LEFT JOIN comments r ON c.id = r.parent_comment_id 
JOIN users u2 ON r.user_id = u2.id 
WHERE c.topic_id = 9 
+0

parent_comment_idを追加してクエリを変更しましたが、次に何をすべきかわかりません。私は2つの返信で1つのコメントがあると言います。これは2つのコメントを生成し、両方とも同じコメントですが異なる返信を持ち、両方の返信に最初のコメントユーザー名があります。 私のメインポストを例に編集しました。 – Dennis

+0

上記の元のクエリを編集して、コメントに返信したユーザーのユーザー名と写真を表示します。 – flayto

+0

いいですね。でも、1つのコメントに対して1つ以上の返信がある場合は、重複したコメント値を出力します。コメントを返信と区別するためにサーバー側のコードで結果配列を変更する必要がありますか? – Dennis

1

が見えます。

まず、私はWordPressの基本テーブルを変更することは良い考えだとは思わない。第二に、あなたはワードプレスの更新で壊れる複雑なコードで終わるでしょう。

ベストは、あなた自身のソリューションを作成する場合、私はコメントの返信のために別のテーブルを作成すると言うでしょうそれでもIntense Comments

のようなプラグインを使用しています。 a)に新しいテーブルがこの

`CREATE TABLE IF NOT EXISTS `comment_replies` (
    `id` int(12) NOT NULL AUTO_INCREMENT, 
    `parent_comment_id` int(12) NULL, 
    `comment` text, 
    `user_id` int(12) DEFAULT NULL, 
    `topic_id` int(12) NOT NULL, 
    `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id` (`topic_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

Bのようになります。)あなたはこのよう

$comment_ids = array_map('intval', array_keys($comments)); 
sort($comment_ids); 
$comments_id_list = join(',', $comment_ids); 

$query = "SELECT c.id, c.comment, c.user_id, u.username, u.photo 
FROM (comment_replies c) 
JOIN users u ON c.user_id = u.id 
WHERE c.parent_comment_id IN ($comments_id_list)" 

$replies = $wpdb->get_results($query); 
$replies_by_parent = array(); 

foreach (array_keys($replies) as $i) {   
    $replies_by_parent [$replies[$i]->id] = array(); 
} 
foreach (array_keys($replies) as $i) {   
    $replies_by_parent [$replies[$i]->id][] =& $replies[$i]; 
} 

Cにそれらを取得したい)今すぐあなたのコメントをループ内で、あなたはこの

のような回答を得ることができます
foreach ( $replies_by_parent [$parent_id] as $reply) {    
     echo $reply->comment; 
    } 
+0

私はwordpressを使用していませんが、解決策はかなりよく見えます。私はそれが私のために最適かどうかを調べるためにそれをさらに見なければならない。 – Dennis

1

これはすべてうまくいくようですが、テーブルに100万行以上が含まれているとしたらどうですか?いくつかのコメントは数十万行離れている可能性があります。これらのクエリはどのように実行されますか?

+0

それは本当ですが、今はそうは考えにくいので、扱うデータが多い場合は、2つのテーブルに分割するのが最善の方法だと思います。 – Dennis

関連する問題