Wie meine Kommentatoren wissen, zeige ich bei jedem Kommentar an, wie viele Kommentare dieser Kommentator hier bisher geschrieben hat (genauer gesagt: wie viele unter demselben Namen abgegeben wurden; mehr zu dieser Unterscheidung später). Über die Details und die Neuerungen Ende letzten Jahres wollte ich schon länger mal schreiben, zumal auch manche andere davon profitieren könnten…
Ursprünglich geschah dies – natürlich ohne extra Plugin (und ohne Abacus
) – mit einer einfachen Datenbankabfrage, die in der Kommentarausgabe aufgerufen wird:1
$c_count = (int) $wpdb->get_var( "SELECT COUNT(*) AS comments FROM $wpdb->comments WHERE comment_author='".$wpdb->escape($comment->comment_author)."' AND comment_type='' AND comment_approved='1'");
Das Problem dabei: eine Datenbankabfrage pro Kommentar. Das ist kein so großes Problem, wenn es wenige Kommentare zum Beitrag oder insgesamt wenige Kommentare gibt. Aber je mehr Kommentare, je mehr verschiedene Kommentatoren und je seltenere Kommentatoren es gibt, umso mehr hat der Datenbankserver zu ackern und umso weniger kann ein Query-Cache – den wohl jeder MySQL-Server hat – oder ein DB-Cache-Plugin ausrichten. Und wenn der Beitrag zwar öfters, aber nicht ständig aufgerufen wird, fallen die Anfragen oder der Beitrag selbst auch immer wieder aus dem Cache raus.
Wenn ein Blog schon einige tausend Kommentare hat, ist diese Abfrage (gerade bei Shared Hosting) recht „teuer“ – ich hatte damals bei Tests Zeiten von bis zu 300 ms pro Anfrage (was ich in aktuellen Tests aber nicht mehr reproduzieren konnte, da waren’s nur ca. 30; keine Ahnung, was sich da geändert hat), was sich bei einem von vielen Leuten vielkommentierten Beitrag so darstellen kann, dass man sehen konnte, wie die Kommentare nach und nach „hingeblättert“ wurden…
Deswegen hab ich mir – nach einem kurzen Test mit einem simplen internen Cache, der sicher noch etwas schneller als eine Anfrage an den MySQL-DB-Cache ist – eine Lösung gebastelt, bei der alle Kommentaranzahlen für den jeweiligen Beitrag auf einmal eingelesen werden, was meinen Tests zufolge nicht wesentlich teurer ist als eine einzelne Abfrage der oben genannten Art:
$ag_number_of_comments_cache = array(); $ag_number_of_comments_inited = false; function ag_number_of_comments ($comment, $before="",$after="") { global $wpdb,$ag_number_of_comments_cache,$ag_number_of_comments_inited; if (!$ag_number_of_comments_inited) ag_number_of_comments_post ((int) $comment->comment_post_ID); if ($comment->comment_type=="") { $c_count = (int) $ag_number_of_comments_cache[ mb_strtolower($comment->comment_author) ]; echo $before."<span class=\"comments-by-author\">".($c_count==1?__('1 Comment'):$c_count." ".__('Comments'))."</span>".$after; } } function ag_number_of_comments_post ($post_ID) { global $wpdb,$wp_query,$ag_number_of_comments_cache,$ag_number_of_comments_inited; if ($post_ID==0) return; $ag_number_of_comments_inited = true; $comments = $wp_query->comments; $authors_sql = '0'; foreach ($comments as $c) { if ( ($c->comment_type=='') && ($c->comment_approved=='1') ) { $authors_sql .= " OR comment_author='".$wpdb->escape(mb_strtolower($c->comment_author))."'"; } } $authorcounts = $wpdb->get_results( "SELECT comment_author, COUNT(*) as comments FROM $wpdb->comments WHERE comment_type='' AND comment_approved='1' AND ($authors_sql) GROUP BY comment_author"); foreach ($authorcounts as $a) { $ag_number_of_comments_cache[mb_strtolower($a->comment_author)] = (int) $a->comments; } }
Eingefügt wird dieser Code am besten natürlich in die functions.php des Themes (auf jeden Fall nach dem <?php am Anfang und vor dem ?> am Ende der Datei!) und aufgerufen dann an der geeigneten bzw. gewünschten Stelle in der Kommentarausgabeschleife in der comments.php2, etwa vor oder nach der Datumsausgabe, mit diesem PHP-Funktionsaufruf:
Bzw. wenn es mitten im HTML-Code stehen soll, natürlich in PHP-Tags eingeschlossen:
Mit den beiden zusätzlichen Parametern kann man noch etwas davor- und dahintergestellten Text angeben, für eine eingeklammerte Ausgabe etwa:
Im Theme-CSS lässt sich das ganze dann mit der Klasse .comments-by-author ansprechen und stylen, falls gewünscht.
Zur eingangs erwähnten Zählung der Kommentare nur nach dem Namen möchte ich noch sagen, dass ich das zwar auch nicht optimal finde, da so mitunter verschiedene Leute, die mit demselben, i.d.R. „normalen“ Namen kommentieren, nicht unterschieden werden können. Nun könnte man zusätzlich die E-Mail-Adresse als Unterscheidungskriterium hinzufügen – doch wenn diese sich ändert (was bei ein paar Kommentatoren schon der Fall war), ist das Ergebnis auch nicht das gewünschte, genausowenig wie bei der URL, wo noch öfter „falsche Unterschiede“ auftreten, weil mal ein „/“ am Ende angegeben wurde und mal nicht. Deswegen belasse ich es beim Namen als Kriterium.
Übrigens wird die Groß-/Kleinschreibung auch nicht unterschieden – schon der Vergleich in MySQL kümmert sich nicht darum, weshalb eine entsprechende Umwandlung in PHP mittels mb_strtolower nötig ist; diese Funktion, die ordentlich mit Umlauten und Sonderzeichen umgehen kann, gibt’s ab PHP 4.3.0 (was heutzutage kein Problem sein sollte).
Nun denn, vielleicht hilft dieser Tip dem einen oder anderen. Es mag nicht der perfekte Code sein, denn auch wenn ich manchmal besserwisserisch korrigieren kann, bin ich kein PHP-Guru.
Also sind Verbesserungsvorschläge sowie Anregungen und Fragen natürlich willkommen.
Foto: Monika Adamczyk – Fotolia.com
- Das Syntax-Highlighting des Codes hab ich hier online erstellt, musste dann aber noch die einzelnen Anführungszeichen durch
'ersetzen, damit WordPress sie nicht in ihre hübsche Variante umwandelt. Vielleicht finde ich fürs nächste Mal einen Highlighter, der auch das noch berücksichtigt… [↩] - Wenn ihr dort nur einen Aufruf der Funktion
wp_list_comments()ohne Callback-Parameter findet, wird es etwas komplizierter – dann ließe es sich vielleicht in den Filterget_comment_dateoderget_comment_authoreinhängen und somit vor/nach diesen ausgeben, aber das ist zu viel für diesen Beitrag; falls jemand ein Plugin dafür kennt – oder für die, die generell nicht gern im Code rumpfriemeln –, könnt ihr ja Bescheid sagen. [↩]
If you think you need to go
If you wanted to be free
There's one thing you need to know
And that's that you can't count on me
Counting Crows, "You Can't Count On Me"
Ähnliche Beiträge:
- Coming soon… 28.11.2008 (2)
- Es blüht wieder 10.01.2008 (1)
- Etwas fürs Archiv (1):
Geordnetes Monatsarchiv 17.06.2010 (6) - ZwoSieben 12.12.2008 (14)
- Tadaaa! 29.11.2008 (27)

Thomas 1 27.01.2010 um 22:17
82 Kommentare
zitieren
Guru biste vielleicht keiner, aber dennoch ist das eine ganz ansehentliche Konstruktion ohne weiteren Plugin-Blasebalg. Mal sehen wann ich das verwerten kann. Besten Dank für den Tipp
cimddwc 27.01.2010 um 23:15
3748 Kommentare
zitieren
Twitter: cimddwc
Gern geschehen. Und wie gesagt, bei Fragen und Problemen…
in die nächstgelegene Glaskugel schauen.juliaL49 2 28.01.2010 um 10:00
859 Kommentare
zitieren
Twitter: 49suns
Ah, sehr schön, das wird sich vor allem beim Rätseln positiv auswirken
cimddwc 28.01.2010 um 10:33
3748 Kommentare
zitieren
Twitter: cimddwc
Grad beim Rätseln hilft auch schon der DB-Cache, weil es ja wenige Rätsler sind, die viele Kommentare schreiben. Ich hatte es bei mir v.a. bei den 2012-Prophezeiungen und der Wahrsagerin bemerkt…
Markus 3 30.01.2010 um 18:18
11 Kommentare
zitieren
count(*) ist grundsätzlich immer nur die Notlösung wenn wirklich kein einzelnes Feld gewählt werden kann. Vielleicht kannst du das noch ändern, dann wird die Abfrage schneller
cimddwc 30.01.2010 um 18:55
3748 Kommentare
zitieren
Twitter: cimddwc
Ich wüsste nicht, wie – außer dass man die Zahlen irgendwo anders extra speichert, denn ein eigenes Feld gibt’s so nicht. Oder hast du eine andere Idee?
Frank 4 01.02.2010 um 11:11
5 Kommentare
zitieren
WordPress stellt für diesen Zweck eine Lösung bereit –
get_comment_count();, man muss also keinen Zusatzcode verwenden, siehe Beitrag dazu.cimddwc 01.02.2010 um 12:35
3748 Kommentare
zitieren
Twitter: cimddwc
Aber diese Funktion liefert doch auch nur Gesamtwerte und nicht die Kommentare pro Kommentator.
Frank 01.02.2010 um 12:53
5 Kommentare
zitieren
Korrekt; sorry, muss ich überlesen haben. Aktuell kann man den where-Parameter dort nicht ansprechen und damit ist deine Select-Abfrage natürlich notwendig.
Pingback: Sommerfrische im Blog – Spontis aufgehübscht – Spontis Weblog 5 01.07.2010 um 22:36