2009-08-11 3 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», но я не уверен. Если я могу выбрать все комментарии и комментарии в одном запросе, а если добавить новый столбец «ответ», я не уверен, как сортировать их получать каждый комментарий с каждым ответом.

Я хотел бы получить совет относительно того, как с этим бороться.

Edit:

После приведенных ниже ответов о добавлении результата parent_comment_id в этом виде массива от 1 комментарий и 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 в базу данных и вместо того, чтобы присоединиться к ответам, я только что выбрал все комментарии сразу для сортировки комментариев и ответов на сервере -side код, Heres запрос:

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 

Заметим, однако, что с этим запросом ваши ответы будут также отображаться не только в столбце «ответ», но также в столбце «комментарий» в виде дополнительных строк с нулевым или большим количеством ответов.

Чтобы показать имя пользователя, ответившего на комментарий, вам нужно будет дважды присоединиться к таблице пользователей (сначала для пользователя, разместившего исходный комментарий, и снова для пользователей, которые ответили). Попробуйте этот запрос, чтобы показать имена пользователей, которые ответили:

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 и изменил запрос, но я не уверен, что делать дальше. Допустим, у меня есть 1 комментарий с 2 ​​ответами, это создаст 2 комментария, оба будут иметь один и тот же комментарий, но разные ответы, и оба ответа будут иметь первое имя пользователя. Я отредактировал свое основное сообщение с примера. – Dennis

+0

Я отредактировал исходный запрос выше, чтобы он показывал имя пользователя и фотографию пользователей, которые ответили на комментарий. – flayto

+0

Выглядит неплохо, но он все равно выводит дублируемое значение комментария, где у вас есть более одного ответа для одного комментария, мне нужно изменить массив результатов на серверный код, чтобы отделить комментарии от ответов? – Dennis

1

Похоже, вы работаете с WordPress, добавив parent_comment_id бы идеальным решением, но не в этом случае.

Во-первых, я не думаю, что изменение основных таблиц WordPress - хорошая идея. Во-вторых, вы получите сложный код, который сломается с обновлениями wordpress.

Лучше всего использовать плагин как Intense Comments

Все еще, если вы хотите создать собственное решение, я бы сказал, создать еще одну таблицу для комментариев ответов. а) Ваша новая таблица будет выглядеть следующим образом

`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 

б) Вы бы принести им этот путь

$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]; 
} 

с) Теперь в вашем комментарии цикла вы можете получить ответы, как это

foreach ( $replies_by_parent [$parent_id] as $reply) {    
     echo $reply->comment; 
    } 
+0

Я не использую Wordpress, но решение выглядит неплохо. Мне нужно больше взглянуть на него, чтобы увидеть, насколько он оптимален для меня. – Dennis

1

Это похоже на все хорошо, но как насчет таблицы, содержащей более миллиона строк? и некоторые комментарии могут составлять сотни тысяч строк. как эти запросы будут выполняться?

+0

Это правда, но сейчас очень маловероятно, я думаю, что лучший способ - разделить их на две разные таблицы, если у вас есть много данных для обработки. – Dennis