2009-08-11 6 views
9

J'ai pensé à celui-ci depuis un certain temps maintenant, j'ai besoin d'un moyen d'ajouter des réponses aux commentaires dans la base de données, mais je ne sais pas comment procéder.mysql structure pour les commentaires et les réponses de commentaires

Ceci est mon commentaire actuellement la table (ne dit pas grand-chose, mais son démarrage):

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 ; 

et voici ma requête en cours:

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 

Une option serait de créer un nouvelle table appelée "comment_replies" mais je ne suis pas sûr Si je suis capable de sélectionner tous les commentaires et réponses de commentaires dans une requête, et Si j'ajoute une nouvelle colonne appelée "répondre" je ne sais pas comment les trier obtenir chaque commentaire avec chaque réponse.

Je voudrais obtenir des conseils sur la façon de faire face à cela.

Edit:

Après les réponses ci-dessous sur l'ajout de résultat parent_comment_id dans ce type de tableau de 1 commentaire et 2 réponses:

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

Comment dois-je traiter ce tableau pour travailler avec elle, Est-il possible de séparer le commentaire des réponses?

Répondre

3

J'ai décidé d'ajouter la colonne parent_id dans la base de données et au lieu de gauche rejoindre les réponses je viens de sélectionner tous les commentaires à la fois pour plus tard trier les commentaires et les réponses avec le serveur Code -side, Heres la requête:

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 

Maintenant, je passe le résultat de la requête à la fonction ci-dessous afin que chaque réponse sera ajouté comme un tableau à l'intérieur du tableau de commentaires, donc en gros il retourne un tableau multidimensionnel.

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

Quelle est la fonction 'array_search_key' - ce n'est pas une fonction de bibliothèque PHP standard – HorusKol

+0

Comment fonctionne la pagination? – Mrusful

+0

où est la fonction array_search_key ?? existe-t-il en php? –

1

Une réponse de commentaire est un commentaire avec un parent comment_id. Essayez d'ajouter comment_id en tant que champ à votre table de commentaires. Ce que vous obtiendrez est une structure arborescente.

Si vous souhaitez récupérer un arbre entier de commentaires, le mieux est d'utiliser un ensemble imbriqué (https://wiki.htc.lan/Hierarchy_model). Mais c'est une solution plus compliquée.

Voici quelques plus d'informations de MySQL: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

Ajouter une colonne parent_comment_id à la table de votre commentaire. Rendez-le facultatif. Lorsque vous interrogez, vous pouvez joindre tous les commentaires enfants à chaque parent. Comme un peu de dénormalisation sélective (légère redondance), vous pouvez vous assurer que topic_id est également défini sur les commentaires enfants, ce qui vous permet de les retirer un peu plus facilement (en supposant que vous allez afficher tous les commentaires enfants dans le fil principal des commentaires via des requêtes ajax plus petites).

Créez la présentation dont vous avez besoin, ajoutez les résultats dans memcached (ou un fichier plat, ou une mémoire ... quelle que soit la mise en cache) et définissez-le.

4

Si vous voulez que les gens puissent répondre aux réponses (ie avoir une hiérarchie de réponses comme dans un forum de discussion en ligne, par exemple), alors j'ajouterais un champ parent_comment_id optionnel à la table des commentaires .

Votre table ressemblerait à ceci

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

Votre requête montrant tous les commentaires et réponses serait quelque chose comme:

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 

Notez cependant que cette requête vos réponses seraient également apparaître non seulement dans la colonne "reply", mais aussi dans la colonne "comment" en tant que lignes supplémentaires avec zéro ou plusieurs réponses.

Pour afficher le nom d'utilisateur des utilisateurs qui ont répondu à un commentaire, vous devrez vous connecter deux fois à la table des utilisateurs (d'abord pour l'utilisateur qui a posté le commentaire original, puis pour le ou les utilisateurs ayant répondu). Essayez cette requête pour afficher les noms des utilisateurs qui ont répondu:

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

J'ai ajouté le parent_comment_id et modifié la requête, mais je ne sais pas quoi faire ensuite. Disons que j'ai 1 commentaire avec 2 réponses, cela générerait 2 commentaires, les deux auront le même commentaire mais des réponses différentes et les deux réponses auront le premier nom d'utilisateur de commentaires. J'ai édité mon poste principal avec un exemple. – Dennis

+0

J'ai modifié la requête originale ci-dessus afin qu'elle affiche le nom d'utilisateur et la photo des utilisateurs qui ont répondu à un commentaire. – flayto

+0

Cela semble bien, mais il produirait toujours une valeur de commentaire dupliquée où vous avez plus d'une réponse pour un commentaire, dois-je modifier le tableau de résultats avec le code côté serveur pour séparer les commentaires des réponses? – Dennis

1

On dirait que vous travaillez avec WordPress, en ajoutant parent_comment_id aurait été une solution idéale, mais pas dans ce cas.

Premièrement, je ne pense pas que la modification des tables de base de WordPress soit une bonne idée. Deuxièmement, vous finirez avec un code complexe qui va rompre avec les mises à jour wordpress.

Le mieux est d'utiliser un plugin comme Intense Comments

encore si vous voulez créer votre propre solution, je dirais créer une autre table pour les réponses de commentaire. a) Votre nouvelle table ressemblerait cette boucle

`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) Vous souhaitez les récupérer ainsi

$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) Maintenant, au sein de votre commentaire, vous pouvez obtenir les réponses comme celui-ci

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

Je n'utilise pas wordpress, mais la solution semble assez bonne. Je dois regarder plus loin pour voir si c'est optimal pour moi. – Dennis

1

cela semble tout bon mais qu'en est-il si la table contenait plus d'un million de lignes? et certains commentaires pourraient être séparés par des centaines de milliers de lignes. Comment ces requêtes fonctionneront-elles?

+0

C'est vrai, mais c'est très improbable en ce moment, je pense que le meilleur moyen serait de les séparer à deux tables différentes si vous avez autant de données à gérer. – Dennis

Questions connexes