2009-08-11 184 views
9

我一直在想這個問題已經有一段時間了,我需要一種方法來在數據庫中添加對評論的回覆,但我不知道如何繼續。用於評論和評論回覆的mysql結構

這是我目前意見表(不說多,但它的一個開始):

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 ; 

這裏是我當前的查詢:

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 

一種選擇是創建一個新表名爲「comment_replies」,但我不確定如果我能夠在一個查詢中選擇所有評論和評論回覆,並且如果我添加一個名爲「回覆」的新列,我不知道如何將它們排序通過每個回覆獲得每條評論。

我很想得到一些關於如何處理這個問題的建議。

編輯:

繼約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 2012-10-14 07:37:33

+0

如何工作分頁? – Mrusful 2016-02-06 19:36:38

+0

哪裏是array_search_key函數?它存在於PHP中嗎? – 2017-01-18 05:42:11

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 

然而要注意與此查詢您的回覆也將不僅顯示了在「回覆」列中,而且在「評論」列中顯示爲每個都有零個或多個回覆的附加行。

要顯示回覆評論的用戶的用戶名,您需要加入兩次用戶表(首先發布原始評論的用戶,以及回覆的用戶)。試試這個查詢,以顯示誰回答用戶的用戶名:

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條評論和2條回覆,這會生成2條評論,兩條評論的評論相同但回覆不同,兩條回覆都會有第一條評論用戶名。 我用一個例子編輯了我的主帖。 – Dennis 2009-08-11 22:13:03

+0

我編輯了上面的原始查詢,以便顯示回覆評論的用戶的用戶名和照片。 – flayto 2009-08-12 13:34:40

+0

看起來不錯,但它仍然會輸出一個重複的註釋值,如果您有多個註釋的回覆,我是否必須使用服務器端代碼更改結果數組以將註釋與回覆分開? – Dennis 2009-08-12 23:09:15

1

您似乎與WordPress的工作,加入了parent_comment_id將是一個理想的解決方案,而不是在這種情況下。

首先,我不認爲修改WordPress基本表是一個好主意。其次,你最終會得到一個複雜的代碼,它會隨着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 2009-08-12 23:15:12

1

這似乎都很好,但如果表中包含超過一百萬行呢?有些評論可能會有數十萬行的分歧。這些查詢將如何執行?

+0

這是真的,但現在它不太可能,我認爲最好的辦法是將它們分成兩個不同的表格,如果你有那麼多的數據需要處理的話。 – Dennis 2009-08-19 13:16:00