2009-08-11 23 views
9

He estado pensando en esto desde hace bastante tiempo, necesito una forma de agregar respuestas a los comentarios en la base de datos, pero no estoy seguro de cómo proceder.estructura de mysql para comentarios y respuestas de comentarios

Este es mi momento, comentario de la tabla (no dice mucho, pero es un inicio):

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 ; 

y aquí está mi consulta actual:

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 

Una opción sería la creación de una nueva tabla llamada "comment_replies" pero no estoy seguro si puedo seleccionar todos los comentarios y respuestas de comentarios en una consulta, y si agrego una nueva columna llamada "reply" no estoy seguro de cómo ordenarlos para obtener cada comentario con cada respuesta.

Me gustaría obtener algunos consejos sobre cómo lidiar con esto.

Editar:

Siguiendo las respuestas a continuación sobre la adición resultado parent_comment_id en este tipo de matriz a partir de 1 comentarios y 2 respuestas:

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!" 
    } 
} 

Cómo debería procesar esta matriz para trabajar con él, ¿Es posible separar el comentario de las respuestas?

Respuesta

3

Decidí agregar la columna parent_id en la base de datos y en vez de unirme a las respuestas, seleccioné todos los comentarios a la vez para ordenar los comentarios y respuestas con el servidor código -side, aquí está la pregunta:

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 

Ahora pasa el resultado de la consulta a la función debajo de modo que cada respuesta se añadirá como una matriz dentro de la gama comentario, así que básicamente devuelve una matriz multidimensional.

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

¿Cuál es la función 'array_search_key' - no es una función de biblioteca estándar PHP – HorusKol

+0

¿Cómo funciona la paginación? – Mrusful

+0

¿dónde está la función array_search_key ?? ¿existe en php? –

1

Una respuesta de comentario es un comentario con un padre comment_id. Intente agregar comment_id como un campo a su tabla de comentarios. Lo que obtendrás es una estructura similar a un árbol.

Si desea recuperar un árbol entero de comentarios, su mejor opción es utilizar un conjunto anidado (https://wiki.htc.lan/Hierarchy_model). Pero esa es una solución más complicada.

Aquí hay más información de MySQL: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

añadir una columna a la tabla parent_comment_id comentarios. Hazlo opcional. Cuando realiza una consulta, puede unir todos los comentarios secundarios a cada padre. Como un poco de desnormalización selectiva (ligera redundancia), puede asegurarse de que topic_id esté configurado también en los comentarios secundarios, lo que le permite sacarlos un poco más fácilmente (suponiendo que va a mostrar todos los comentarios secundarios en el hilo principal de comentarios y no a través de solicitudes ajax más pequeñas).

Cree la presentación como lo necesite, mezcle los resultados en memcached (o un archivo plano, o memoria ... sin importar que esté almacenando en caché) y listo.

4

Si desea que las personas puedan responder a las respuestas (es decir, tener una jerarquía de respuestas como las que vería en un foro de mensajes en línea), agregaría un campo opcional parent_comment_id a la tabla de comentarios .

Su mesa se vería así

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

Su consulta muestra todos los comentarios y respuestas sería algo así como:

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 

Nota sin embargo, que con esta consulta sus respuestas serían también mostrará no sólo en la columna 'respuesta', pero también en la columna 'comentario' como filas adicionales, cada una con cero o más respuestas.

Para mostrar el nombre de usuario de los usuarios que respondieron un comentario, deberá unirse dos veces a la tabla de usuarios (primero para el usuario que publicó el comentario original y nuevamente para el usuario que contestó). Intentar esta consulta para mostrar los nombres de los usuarios que contestaron:

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

Agregué el parent_comment_id y cambié la consulta, pero no estoy seguro de qué hacer a continuación. Digamos que tengo 1 comentario con 2 respuestas, esto generaría 2 comentarios, ambos tendrán el mismo comentario pero diferentes respuestas y ambas respuestas tendrán los primeros comentarios nombre de usuario. Edité mi publicación principal con un ejemplo. – Dennis

+0

He editado la consulta original anterior para que muestre el nombre de usuario y la foto de los usuarios que respondieron un comentario. – flayto

+0

Se ve bien, pero aún generaría un valor de comentario duplicado en el que tiene más de una respuesta para un comentario, ¿tengo que modificar la matriz de resultados con el código del lado del servidor para separar los comentarios de las respuestas? – Dennis

1

Parece que se está trabajando con WordPress, agregando un parent_comment_id habría sido una solución ideal, pero no en este caso.

En primer lugar, no creo que modificar las tablas básicas de WordPress sea una buena idea. En segundo lugar, terminará con un código complejo que se romperá con las actualizaciones de wordpress.

Lo mejor es usar un plugin como Intense Comments

embargo, si desea crear su propia solución, yo diría que crear otra tabla para las respuestas de comentarios. a) Su nueva tabla se vería así

`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) Se les gustaría traes esta manera

$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) Ahora dentro de su bucle de comentarios puede obtener las respuestas como esta

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

No uso wordpress, pero la solución parece bastante buena. Tengo que mirar más adentro para ver si es óptimo para mí. – Dennis

1

esto parece todo bien, pero ¿qué pasa si la tabla contiene más de un millón de filas? y algunos comentarios podrían estar separados por cientos de miles de filas. ¿cómo se realizarán estas consultas?

+0

Eso es cierto, pero es muy poco probable en este momento, creo que la mejor manera sería separarlos en dos tablas diferentes si tiene tantos datos que manejar. – Dennis

Cuestiones relacionadas