2009-08-11 33 views
9

Ho pensato a questo per un po 'di tempo, ho bisogno di un modo per aggiungere risposte ai commenti nel database, ma non sono sicuro di come procedere.struttura mysql per commenti e commenti risposte

Questo è il mio momento commentare tavolo (non dice molto, ma è un inizio):

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 ; 

e qui è la mia domanda attuale:

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 possibilità sarebbe quella di creare un nuova tabella denominata "comment_replies" ma non sono sicuro Se sono in grado di selezionare tutti i commenti e le risposte dei commenti in una query e se aggiungo una nuova colonna chiamata "reply" non sono sicuro su come ordinarli ricevi ogni commento con ogni risposta.

Mi piacerebbe avere qualche consiglio su come gestirlo.

Edit:

Seguendo le risposte qui sotto sull'aggiunta risultato parent_comment_id in questo tipo di matrice da 1 commento e 2 risposte:

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

Come dovrei elaborare questa matrice per lavorare con esso, È possibile separare il commento dalle risposte?

risposta

3

Ho deciso di aggiungere la colonna parent_id nel database e invece di unire a sinistra le risposte ho appena selezionato tutti i commenti in una volta sola per ordinare i commenti e le risposte con il server Codice -side, ecco la domanda:

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 

Ora passo il risultato della query alla funzione di seguito in modo che ogni risposta verrà aggiunto come un array all'interno del commento matrice, in modo sostanzialmente restituisce un array multidimensionale.

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

Qual è la funzione 'array_search_key' - non è una funzione di libreria standard di PHP – HorusKol

+0

Come funziona l'impaginazione? – Mrusful

+0

dov'è la funzione array_search_key ?? esiste in PHP? –

1

Una risposta di commento è un commento con un genitore comment_id. Prova ad aggiungere comment_id come campo alla tua tabella dei commenti. Quello che otterrete è una struttura ad albero.

Se si desidera recuperare un intero albero di commenti, la soluzione migliore è utilizzare un set nidificato (https://wiki.htc.lan/Hierarchy_model). Ma questa è una soluzione più complicata.

Ecco qualche informazione in più da MySQL: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

aggiungere una colonna parent_comment_id al vostro tavolo commenti. Rendi opzionale. Quando si esegue una query, è possibile unire tutti i commenti secondari a ciascun genitore. Come un po 'di denormalizzazione selettiva (leggera ridondanza) puoi assicurarti che topic_id sia impostato anche sui commenti figlio, permettendoti di estrarli tutti un po' più facilmente (supponendo che tu stia andando a visualizzare tutti i commenti secondari nel thread principale dei commenti e non tramite richieste ajax più piccole).

Costruisci la presentazione che ti serve, getta i risultati in memcached (o in un file flat, o memoria ... comunque stai facendo il caching) e sei pronto.

4

Se si desidera che le persone siano in grado di rispondere alle risposte (ovvero disporre di una gerarchia di risposte come si vedrebbe in, ad esempio, un forum di messaggi online), aggiungerei un campo parent_comment_id facoltativo alla tabella dei commenti .

La tabella sarà simile a questa

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

Vostri criteri che mostra tutti i commenti e le risposte sarebbe qualcosa di simile:

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, tuttavia, che con questa query vostre risposte sarebbe anche presentarsi non solo nella colonna 'reply', ma anche nella colonna 'comment' come righe aggiuntive ognuna con zero o più risposte.

Per mostrare il nome utente degli utenti che hanno risposto a un commento, è necessario unirsi due volte alla tabella degli utenti (prima per l'utente che ha pubblicato il commento originale e nuovamente per gli utenti che hanno risposto). Prova questa ricerca per mostrare i nomi utente degli utenti che hanno risposto:

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

Ho aggiunto il parent_comment_id e ho cambiato la query, ma non sono sicuro di cosa fare dopo. Diciamo che ho 1 commento con 2 risposte, questo genererebbe 2 commenti, entrambi avranno lo stesso commento ma risposte diverse ed entrambe le risposte avranno i primi commenti username. Ho modificato il mio post principale con un esempio. – Dennis

+0

Ho modificato la query originale sopra in modo che mostri il nome utente e la foto degli utenti che hanno risposto a un commento. – flayto

+0

Sembra buono, ma produrrebbe comunque un valore di commento duplicato in cui si ha più di una risposta per un commento, devo modificare l'array di risultati con il codice lato server per separare i commenti dalle risposte? – Dennis

1

Sembra che si sta lavorando con WordPress, aggiungendo un parent_comment_id sarebbe stata una soluzione ideale, ma non in questo caso.

In primo luogo, non penso che la modifica delle tabelle di base di WordPress sia una buona idea. In secondo luogo, finirai con un codice complesso che si interromperà con gli aggiornamenti di wordpress.

migliore è usare un plugin come Intense Comments

Ancora, se si desidera creare la vostra soluzione, direi a creare un altro tavolo per un commento risposte. a) la nuova tabella sarà simile a questa

`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) Si potrebbe prenderli in questo modo

$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) A questo punto all'interno del tuo ciclo commenti è possibile ottenere le risposte come questo

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

Non uso wordpress, ma la soluzione sembra abbastanza buona. Devo guardare più a fondo per vedere se è ottimale per me. – Dennis

1

questo sembra tutto buono ma che dire se il tavolo conteneva oltre un milione di righe? e alcuni commenti potrebbero essere centinaia di migliaia di righe a parte. come funzioneranno queste query?

+0

Questo è vero, ma è al momento molto improbabile, penso che il modo migliore sarebbe separarli in due tabelle diverse se si hanno tanti dati da gestire. – Dennis