2009-08-11 2 views
9

Ich habe jetzt schon seit geraumer Zeit über diesen nachgedacht, ich brauche eine Möglichkeit, Antworten auf Kommentare in der Datenbank hinzufügen, aber ich bin nicht sicher, wie es weitergeht.mysql Struktur für Kommentare und Kommentar antwortet

Dies ist meine momentan Kommentar Tabelle (nicht viel sagen, aber es ist ein Anfang):

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 ; 

und hier ist meine aktuelle Abfrage:

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 

Eine Möglichkeit wäre, eine erstellen Neue Tabelle namens "comment_replies", aber ich bin mir nicht sicher, ob ich alle Kommentare und Kommentarantworten in einer Abfrage auswählen kann. Wenn ich eine neue Spalte namens "reply" hinzufüge, weiß ich nicht, wie ich sie sortieren soll Bekomme jeden Kommentar mit jeder Antwort.

Ich würde gerne ein paar Ratschläge zu bekommen, wie damit umgehen.

Edit:

Nach den unten Antworten zu parent_comment_id Ergebnis in dieser Art von Array von 1 Kommentar und 2 Antworten ergänzt:

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

Wie soll ich dieses Array verarbeiten, mit ihm zu arbeiten, Ist es möglich, den Kommentar von den Antworten zu trennen?

Antwort

3

Ich habe mich entschieden, die parent_id Spalte in der Datenbank hinzuzufügen und anstatt links beitreten die Antworten Ich habe nur alle Kommentare auf einmal sortiert, um später die Kommentare und Antworten mit Server zu sortieren -side Code, here die Abfrage:

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 

Jetzt gebe ich das Abfrageergebnis an die unten Funktion, so dass jede Antwort wird als ein Array in dem Kommentar-Array hinzugefügt werden, so dass im Grunde gibt es ein mehrdimensionales Array.

+3

Was ist die Funktion 'array_search_key' - es ist keine PHP-Standardbibliotheksfunktion – HorusKol

+0

Wie funktioniert Paginierung? – Mrusful

+0

wo ist die array_search_key Funktion ?? Gibt es das in PHP? –

1

Eine Kommentarantwort ist ein Kommentar mit einem Elternteil Kommentar_ID. Versuchen Sie, comment_id als Feld zu Ihrer Kommentartabelle hinzuzufügen. Was Sie bekommen werden, ist eine baumartige Struktur.

Wenn Sie einen ganzen Baum von Kommentaren abrufen möchten, verwenden Sie am besten einen verschachtelten Satz (https://wiki.htc.lan/Hierarchy_model). Aber das ist eine kompliziertere Lösung.

Hier einige weitere Informationen von MySQL: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

3

eine parent_comment_id Spalte auf Ihre Kommentare Tabelle hinzufügen. Mach es optional. Wenn Sie abfragen, können Sie allen untergeordneten Kommentaren zu jedem übergeordneten Element beitreten. Als ein wenig selektive Denormierung (leichte Redundanz) können Sie sicherstellen, dass topic_id auch auf die untergeordneten Kommentare gesetzt ist, sodass Sie sie alle etwas leichter ziehen können (vorausgesetzt, Sie werden alle untergeordneten Kommentare im Hauptkommentar anzeigen und nicht über kleinere Ajax-Anfragen).

Bauen Sie die Präsentation jedoch benötigen Sie, um die Ergebnisse in Memcached werfen (oder einer flachen Datei oder Speicher ... aber Sie Caching) und Sie werden eingestellt.

4

Wenn Sie wollen, dass die Leute auf die Antworten antworten können (dh eine Hierarchie von Antworten haben, wie Sie sie zB in einem Online-Nachrichtenforum sehen würden), würde ich ein optionales Feld parent_comment_id zur Kommentartabelle hinzufügen .

Ihr Tisch wie diese

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

Ihre Abfrage zeigt alle Kommentare und Antworten wie wäre etwas aussehen würde:

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 

ist jedoch zu beachten, dass bei dieser Abfrage würde Ihre Antworten zeigen sich auch nicht nur in der Spalte "Antwort", aber auch in der Spalte "Kommentar" als zusätzliche Zeilen mit jeweils null oder mehr Antworten.

Um den Benutzernamen der Benutzer anzuzeigen, die auf einen Kommentar geantwortet haben, müssen Sie der Benutzer-Tabelle zweimal beitreten (zuerst für den Benutzer, der den ursprünglichen Kommentar gepostet hat, und erneut für den Benutzer). Diese Abfrage der Benutzernamen der Benutzer zu zeigen, wer antwortete:

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

Ich habe die parent_comment_id hinzugefügt und die Abfrage geändert, aber ich bin mir nicht sicher, was ich als nächstes tun soll. Sagen wir, ich habe 1 Kommentar mit 2 Antworten, dies würde 2 Kommentare generieren, beide haben den gleichen Kommentar aber unterschiedliche Antworten und beide Antworten haben den ersten Kommentar Benutzername. Ich habe meine Hauptpost mit einem Beispiel bearbeitet. – Dennis

+0

Ich habe die obige Abfrage so bearbeitet, dass sie den Benutzernamen und das Foto der Benutzer anzeigt, die auf einen Kommentar geantwortet haben. – flayto

+0

Sieht gut aus, aber es würde immer noch einen doppelten Kommentarwert ausgeben, wenn Sie mehr als eine Antwort für einen Kommentar haben. Muss ich das Ergebnisarray mit serverseitigem Code ändern, um die Kommentare von den Antworten zu trennen? – Dennis

1

Sieht aus wie Sie mit Wordpress arbeiten, das Hinzufügen einer parent_comment_id wäre eine ideale Lösung gewesen, aber nicht in diesem Fall.

Erstens, ich glaube nicht, die WordPress Basistabellen zu ändern, ist eine gute Idee. Zweitens wirst du mit einem komplexen Code enden, der mit WordPress-Updates bricht.

Am besten ist es ein Plugin wie Intense Comments

noch verwenden, wenn Sie Ihre eigene Lösung erstellen möchten, würde ich eine andere Tabelle für einen Kommentar Antworten sagen erstellen. a) Ihre neue Tabelle wie diese

`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 aussehen würde) Sie würden holen sie auf diese Weise

$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) Jetzt in Ihre Kommentare Schleife können Sie die Antworten bekommen wie dieses

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

Ich benutze Wordpress nicht, aber die Lösung sieht ziemlich gut aus. Ich muss mehr darüber schauen, um zu sehen, ob es für mich optimal ist. – Dennis

1

Das scheint alles gut, aber was ist, wenn die Tabelle über eine Million Zeilen enthielt? und einige Kommentare könnten Hunderttausende von Zeilen auseinander liegen. Wie werden diese Abfragen ausgeführt?

+0

Das stimmt, aber es ist sehr unwahrscheinlich im Moment, ich denke, der beste Weg wäre, sie auf zwei verschiedene Tabellen zu trennen, wenn Sie so viele Daten verarbeiten müssen. – Dennis