2009-08-11 182 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