Seit WordPress 2.7 gibt es eine API für den Bereich der Kommentare. Damit kann man auch den PHP-Anteil innerhalb der comments.php entschlacken, je nach eigenem Ermessen. Jean-Baptiste zeigt eine einfache Lösung, um die Kommentare zu zählen. Die Lösung sollte bekannt sein und wird quasi seit der ersten WordPress Veröffentlichung so realisiert. Hinweise dazu gibt es vielfach hier im Blog und im Netz. Wollte man dann aber einen Filter über den Zähler haben, der beispielsweise nur die Trackbacks zählt oder auch nur die Kommentare, die per Formular eingehen, dann scheitert diese Lösung. Außerdem ist das How To doch recht schmal und PHP-Laien könnten in Schwierigkeiten geraten.
Aus diesem Zusammenhang und diverser Fragen zum Thema zeige ich mal zwei einfache Funktionen, die in der functions.php des Themes abgelegt werden und dann willkürlich im Theme genutzt werden können. In der Regel werden sie dann also zur Ausgabe in der comments.php heran gezogen.
/**
* count for Trackback, pingback, comment, pings
*
* so einbinden:
* fb_comment_type_count('ping');
* fb_comment_type_count('comment');
*/
if ( !function_exists('fb_comment_type_count') ) {
function fb_get_comment_type_count( $type='all', $zero = false, $one = false, $more = false, $post_id = 0) {
global $cjd_comment_count_cache, $id, $post;
if ( !$post_id )
$post_id = $post->ID;
if ( !$post_id )
return;
if ( !isset($cjd_comment_count_cache[$post_id]) ) {
$p = get_post($post_id);
$p = array($p);
update_comment_type_cache($p);
}
;
if ( $type == 'pingback' || $type == 'trackback' || $type == 'comment' )
$count = $cjd_comment_count_cache[$post_id][$type];
elseif ( $type == 'pings' )
$count = $cjd_comment_count_cache[$post_id]['pingback'] + $cjd_comment_count_cache[$post_id]['trackback'];
else
$count = array_sum((array) $cjd_comment_count_cache[$post_id]);
return apply_filters('fb_get_comment_type_count', $count);
}
// comment, trackback, pingback, pings, all
function fb_comment_type_count( $type='all', $zero = false, $one = false, $more = false, $post_id = 0 ) {
$number = fb_get_comment_type_count( $type, $zero, $one, $more, $post_id );
if ( $number > 1 )
$output = str_replace('%', number_format_i18n($number), ( false === $more ) ? __('% Comments') : $more);
elseif ( $number == 0 )
$output = ( false === $zero ) ? __('No Comments') : $zero;
else // must be one
$output = ( false === $one ) ? __('1 Comment') : $one;
echo apply_filters('fb_comment_type_count', $output, $number);
}
}
if ( !function_exists('fb_update_comment_type_cache') ) {
function fb_update_comment_type_cache(&$queried_posts) {
global $cjd_comment_count_cache, $wpdb;
if ( !$queried_posts )
return $queried_posts;
foreach ( (array) $queried_posts as $post )
if ( !isset($cjd_comment_count_cache[$post->ID]) )
$post_id_list[] = $post->ID;
if ( $post_id_list ) {
$post_id_list = implode(',', $post_id_list);
foreach ( array('', 'pingback', 'trackback') as $type ) {
$counts = $wpdb->get_results("SELECT ID, COUNT( comment_ID ) AS ccount
FROM $wpdb->posts
LEFT JOIN $wpdb->comments ON ( comment_post_ID = ID AND comment_approved = '1' AND comment_type='$type' )
WHERE post_status = 'publish' AND ID IN ($post_id_list)
GROUP BY ID");
if ( $counts ) {
if ( '' == $type )
$type = 'comment';
foreach ( $counts as $count )
$cjd_comment_count_cache[$count->ID][$type] = $count->ccount;
}
}
}
return $queried_posts;
}
add_filter('the_posts', 'fb_update_comment_type_cache');
}
Sind die beiden Funktionen abgelegt und damit im Theme verfügbar, so könnte die Nutzung für die drei Formen comments, trackbacks und pingbacks zum Beispiel wie folgt aussehen.
if ( function_exists('wp_list_comments') ) {
// WP 2.7 Kommentar Loop
if ( have_comments() ) { ?>
<?php if ( empty($comments_by_type['comment']) ) { ?>
<h2 id="comments"><?php fb_comment_type_count( 'comment' ); ?></h2>
<ol class="commentlist">
<?php wp_list_comments( 'type=comment&callback=fb_theme_comment' ); ?>
</ol>
<?php } ?>
<?php
if ( function_exists( 'fb_comment_type_count' ) ) {
// alternativ type pings fuer trackback + pingback
if ( empty($comments_by_type['pingback']) ) { ?>
<h2 id="pingback"><?php fb_comment_type_count( 'pingback', 'Keine Pingback', 'Ein Pingback', '% Pingbacks' ); ?></h2>
<ol class="pingbacklist">
<?php wp_list_comments('type=pingback'); ?>
</ol>
<?php } ?>
<?php
// alternativ type pings fuer trackback + pingback
if ( empty($comments_by_type['trackback']) ) { ?>
<h2 id="trackback"><?php fb_comment_type_count( 'trackback', 'Keine Trackback', 'Ein Trackback', '% Trackbacks' ); ?></h2>
<ol class="trackbacklist">
<?php wp_list_comments('type=trackback'); ?>
</ol>
<?php }
} ?>
<div class="navigation nav_comments">
<div class="alignleft"><?php previous_comments_link() ?></div>
<div class="alignright"><?php next_comments_link() ?></div>
</div>
<?php } else {
// this is displayed if there are no comments so far
} ?>
Die obige Syntax zeigt nur einen Ausschnitt aus der comments.php und sollte daher in die jeweilige Anforderung eingepasst werden. Im Basis-Theme von mir ist es aktuell nicht drin, kommt aber.
Die obigen Bereiche können natürlich mit anderem Markup ausgestattet werden und die Klassen und IDs sind auch nur beispielhaft. Da sind die Möglichkeiten jedem überlassen und den eigenen Anforderungen anzupassen.
Hinweise, Lob, Verbesserungen oder Kritik - die Kommentare stehen euch wie immer offen, auch wenn die meisten ja eher per Feed hier mitlesen.
Super, genau danach war ich gestern auf der Suche. Danke für diese Lösung!
Hi,
ich würde gerne die Pingbacks/Trackbacks etwas anders darstellen, wenn ich
aufrufe zeigt er mit 2x mal den "Author" an und und noch content.
ich würde gerne nur den "Auhtor" mit Link zum Trackback/Pingback anzeigen.
Ich werde einfach aus dem ganzen nicht so recht schlau.
Das obige Beispiel soll auch nur den EInbau des Zähler verdeutlichen, die Links etc. werden mit den gängigen Template Tags von WP erstellt.
Hi,
um das Beispiel oben aber richtig nutzen zu können macht es Sinn das ergänzend zu posten. Dieses Beispiel hab ich ja auch schon x-mal im Web gefunden, aber nie den Punkt zur Darstellung dazu.
Wenn ich das richtig gesehen habe müsste man wp_list_comments mit einer Callback Funktion aufrufen um das Layout anpassen zu können. Ich habs aber nicht hinbekommen. Auch wenn ich schon einigene kleine Plugins geschrieben hab bekomm ich das nicht ganz auf die Reihe. Bin noch ziemlich frisch im WP Bereich.
Schau dir mal den Code meiner Sandbox an; ab 2.7 muss zusätzlich ein Eintrag in der
header.phpsein, um die threaded comments zu ermöglichen. Ich vermute, dort siehst du es klarer, da diecomments.phpmit allen Inhalten da ist. Ansonsten muss ich mal Zeit finden und ein kleines Tutorial erstellen.Ah ja, vielen Dank.
Das ist doch mal ein Beispiel das man umsetzen kann.
Funktioniert jetzt wunderbar, Danke Frank!
Ich habe in meinem theme dkret3 gerade die Unterstützung eines neuen Plugins eingebaut. Gregs Threaded Comments Numbering bietet eine wunderbar einfache und komfartable Möglichkeit, Kommentare zu nummerieren.
Außerdem werden Unterkommentare entsprechend gezählt (1.1 etc.). Wirklich ein tolles Plugin.
Danke für die ausführliche Anleitung! Mal sehen ob ich damit zurecht komme.
Gruß
Mobe
Hi Frank, ich hab Dein Beispiel für den Kommentarzähler mal bei mir ausprobiert und bis auf eine Kleinigkeit funktioniert das auch. Ich würde gerne die Kommentare getrennt gezählt haben. Als Beispiel: Es liegen zwei Pingbacks, ein Trackback und drei Kommenatre vor. Die Tracks und Pings werden mit dem obigen Codeschnipsel richtig gezählt, nur bei den Kommentaren steht im Zähler "6" anstatt "3" ... wie muss ich das ändern um die "normalen" Comments getrennt zu zählen?
$type == 'comment'ist der Schlüssel. Du kannst also die obige Funkion nutzen und mit Übergabe des Paramter $type den Typ mitgeben, in dem Fall comment.Hi,
bei mir hab ich das "getrennte Zählen" wie folgt gelöst:
/** * Funktion zum zählen der Comments und Pingbacks */ add_filter('get_comments_number', 'comment_count', 0); function comment_count( $count ) { global $id; $comments_by_type = &separate_comments( get_comments('post_id=' . $id) ); return count($comments_by_type['comment']); } function pings_count( $count ) { global $id; $comments_by_type = &separate_comments( get_comments('post_id=' . $id) ); return count($comments_by_type['pings']); }alles klar, habs gerade hinbekommen, was mich in diesem Zusammenhang interessieren würde ist die Ausgabe. Wenn man comments_number nutzt lässt sich die Ausgabe variabel gestalten, also Ein Kommentar, 5 Kommentar(e) bzw. Kein Kommentar als Beispiel. Lässt sich sowas auch für Deine Funktion "fb_comment_type_count" realisieren?
Auf jeden Fall erstmal Danke für die schnelle Antwort und Respekt für Deine mehr als hilfreiche Seite die wirklich klasse Beiträge bereit hält! Grüße, Markus
@Markus: danke für den Hinweis, dass hatte ich damals nicht vorgesehen und nun habe ich es ergänzt. Man hat nun mehr Parameter und ich habe es nicht als reine Ausgabe realisiert, sondern via Filter, wie es WordPress auch macht.
@alle: Bitte schaut euch das Update des COde an, es bietet mehr Möglichkeiten.
@Markus:
Bei mir sieht das so aus:
comments_popup_link(__('Kommentare (0)'), __('Kommentar (1)'), __('Kommentare (%)'));was für ein Service! Klasse Frank, ich bin ja begeistert ... Ich erstelle zwar selbst Webseiten und WordPress-Templates aber was Funktionsprogrammierung angeht bin ich froh, dass es Leute wie Dich gibt die mit Ihrem Know-How weiterhelfen. Ich baue gerade an einem Theme, dass nach Möglichkeit alle wesentlichen Funktionen der neuen WordPress-Version nutzt aber wenn ich mir Dein Basis-Template anschaue geht da noch ne ganze Menge mehr. Die Kommentargeschichte ist ja im neuen WP ein wenig zweischneidig. Auf der einen Seite wird manches vereinfacht, auf der anderen Seite wirds doch wieder komplexer sofern man die Comments wirklich individuell stylen möchte ... auf jeden Fall hat mich Dein Beispiel hier schon ne ganze Ecke weitergebracht ...
@ BongoUser: Danke für den Tipp, ich hoffe das ich irgendwann mal alle Template-Tags im FF parat habe, den comments_popup hatte ich bisher noch garnicht auf dem Schirm ... beste Grüße, Markus
Danke für den Tipp jetztmkann ich endlich auch auf WP 2.7 updaten.
Hallo Frank,
ich habe die getrennte Zählung gemäß deinem Beispiel und dem Code aus der Sandbox nun auch bei mir realisiert. Ist es noch möglich den Code für die Hervorhebung der Kommentare des Blogbetreibers? Bis jetzt benutzte ich immer folgenden Code:
<li id="comment-"comment_author_email == get_the_author_email()) && ($comment->user_id != 0) ) {
echo " class=\"autor_kommentar\"";
} else {
echo " class=\"" . $oddcomment . "\"";
}
?>>
Leider funktioniert das nicht wie gewünscht, hast du eine Lösung?
Ich übergebe beim Aufruf von
wp_list_comment()eine Funktion mit, welche sich um die Ausgabe der Kommentare kümmert. Ist auch so in der Sandbox:<?php if ( empty($comments_by_type['comment']) ) { ?><?php fb_comment_type_count( 'comment' ); ?>
<?php wp_list_comments( 'type=comment&callback=fb_theme_comment' ); ?>
<?php } ?>Diese Funktion hat eine neue Funktion im li-Tag:
comment_class():Diese vergibt die entsprechenden Klassen, so dass ich das Abfragen wie du es zeigst, gar nicht machen muss. Ich habe damit die Klasse
authorbzw.bypostauthordabei und die formatiere ich dann entsprechend.Vielen Dank für den Hinweis, die Funktion kannte ich noch gar nicht. Habe sie jetzt aber implementiert. Doch gleich das nächste Problem, eine leere Weiße Seite wenn ich ein Kommentar abschicke, egal ob ein Angemeldeter oder nicht angemeldeter Benutzer das macht, sowohl bei FF als auch beim IE. Offenbar kommt kein Rücksprung von der wp-comments-post.php - ob es an dem Formular liegt? Ich kann keinen Fehler entdecken.
@Robert: meist liegt es an der
comments.phpdes Themes, da fehlt dann was.Kurioserweise habe ich Testhalber jetzt die Funktion fb_theme_comment, fb_comment_type_count und fb_update_comment_type_cache aus deiner Sandbox übernommen. Die comments.php habe ich zu Testzwecken ebenfalls durch die aus der Sandbox 1:1 ersetzt. Der Fehler bleibt aber der gleiche.
Das Kommentar wird zwar eingetragen und erscheint auch beim erneuten Seitenaufruf, aber die leere Seite wird weiterhin angezeigt und springt nicht zurück.
sauberes WordPress?, geht es mit dem default-Theme; meine Sandbox klappt im Test
Gute Idee, ein anderes Theme, dasselbe Problem. Plugins deaktiviert und probiert. Aha! Ich sollte noch einen Kaffee trinken, der Comment Mailer hat einfach keine Eingabe erhalten, weil ich das entsprechende Feld noch nicht eingefügt hatte. Wie peinlich!
Du kannst diese Kommentare gerne löschen
Wunderbar, dann passte es ja nun. Viel Erfolg.
Kaffee - ah ja, ich nun auch mal.
EIne Frage ergibt sich jetzt doch noch. Wenn die Abfrage kein Pingback vorfindet, gibt es trotzdem ein leere und damit nicht valide Liste aus. Kann man die Abfrage nicht so modifizieren, das sie im Falle keiner Pingbacks auch nichts ausgibt (auch keine Überschrift)?
if ( empty($comments_by_type['pingback']) ) {Das fragt ab, ob es pingbacks gibt, wenn nein, dann wird auch nichts ausgegeben.
Davon bin ich auch ausgegangen, leider funktioniert das offenbar nicht. Der Code im Zusammenhang:
if ( empty($comments_by_type['pingback']) ) { ?>Leider bekomme ich als Ausgabe immer die Überschrift und eine leere Tabelle. Ist das vielleicht ein php 4/5 Problem?
nein, empty ist kein PHP5 Problem und hier wird nur gefragt, ob es Einträge gibt, sonst gib nix aus, was in meinen Tests auch sauber klappt.
Hi Frank, ich kann das kleine Problem von Robert bestätigen. Sofern keine Tracks oder Pings vorhanden sind wird sowohl die Headline "Keine Trackback" bzw. "keine Pingback" ausgegeben als auch eine leere Liste (ol class pingbacklist bzw. ol class trackbacklist) ... Ich hab sowohl Deine Oiginal-comments.php als auch die functions.php des Basis-Themes probiert als auch den Code aus diesem Beitrag hier, das Ergebnis ist immer eine leere OL wenn keine Tracks oder Pings vorhanden sind ... Grüße, Markus
@Markus: ok, schaue es mir nochmal an; eventuell reicht es wenn man die Prüfung negiert, mit
!empty($comments_by_type['pingback']).Danke Frank, das wars schon ... mit der Negierung funktioniert es. Bin gerade über dem Styling meiner Kommentare im neuen Template und gleich über eine weitere Sache gestolpert: Wie lassen sich die Kommentar-Nummern ausgeben? Mit der alten Kommentarfunktion ging das per php foreach ($comments as $comment) : $comment_count++; und dann an geeigneter Stelle per "echo count" ... das lässt sich doch bestimmt auch in Deiner Funktion einbauen, hab leider zu wenig Planung von PHP um da selbst rumzuschrauben
Noch ein Nachtrag: Beim Bau meines Themes ist mir aufgefallen, dass bei Nutzung einer individuellen Ausgabe der Kommentare per Callback grundsätzlich ein schließendes /li ausgeben wird. Am Beispiel Deiner Funktion fb_theme_comment bedeutet das, dass man das schließende /li nicht notiert da WordPress diese aus irgendeinem Grund bereits selber ausgibt, ansonsten endet die Ausgabe mit zwei /li´s (WP-Bug?)
Greets, Markus
@Markus: stimmt, habe ich auch bemerkt, wollte es aber noch prüfen. Finde es sehr komisch.
Ich hab das jetzt auch mal so eingebaut und hab bisher auch das Problem, dass bei der Kombination kein Trackback/Kommentar das ol Tag der Trackbacks angezeigt wird. Aber mir ist auch nicht so ganz klar, wieso die Abfrage empty($comments_by_type['trackback']) nicht negiert sein muss (obwohl dann entsprechend gar nichts angezeigt wird). Das Array sollte doch gerade nicht leer sein, damit der Fall eintritt. Gibt es da evtl. eine andere Möglichkeit abzufragen, ob Trackbacks/Kommentare vorhanden sind?
Nebenbei: Das schließende /li Tag kommt durch die integrierte reply Funktion. Antwortet man auf ein Kommentar, wird dieser innerhalb des li Tags eingebunden.
Hello,
I have some problems with reference from fb_update_comment_type_cache function with PHP 5.3.0.
It works fine without it but I don't really know the utility of that function.
Hope you speak english,
Alex
@Alex: this function is only for reset the cache of WordPress when it add a comment.
Thanks for quick answer.
And what's happen when I remove & from
function fb_update_comment_type_cache(&$queried_posts)
There is some incompatibility with reference in PHP 5.3.0
Regards,
Alex
Yes, you can delete this function, include the filter.
Another problem, does not seem to work on attachments. Did you know about this or it's just me?
Also, update_comment_type_cache() does not exists, it's fb_update_comment_type_cache() right?
Regards,
Alex
@Alex: yes, this is the correct function. Please see the WP Basis Theme, i use this function on this theme and you can read and use the syntax.
Thanks for the elucidation.
Any clues about that attachments problem?
Regards,
Alex
@Alex: do you men the attachment-Template?
Not really, the attachment default template is single.php
For example on posts (single.php) comments/trackbacks number are displayed but on attachments (same template - single.php) are not.
Any ideas?
@Alex: i dont understand the problem with the attachments; please can you write more infos. My functions are filter for track-, pingbacks and comments, not attachments. Sorry and i hope you can send me your wish.
Yes, but you can add comments to attachments right?
This is my problem.
echo fb_get_comment_type_count('comment') ---- does not display anything on attachment page.
@Alex: ok, also the attachment-Template or the default template with a attachment. I will test this and write a solution.
Hallo Frank,
beim studieren deienes Codes ist mir die gleiche Frage wie bei Mark (#31) aufgekommen.
Viele Grüße,
Vlad
@Perun: im Code habe ich das aktuell nicht drin, in einer anderen Seite mache ich das via JS, da es nur dann Mehrwert ist, wenn JS aktiv ist:
<script type="text/javascript">
//<![CDATA[
document.documentElement.className += " js";jQuery(document).ready( function($){var li=$('#kommentarbereich .tabs').size();if(li==2){$('#kommentarbereich').accessibleTabs({tabhead:"h6",tabbody:".tabs",fx:"fadeIn"});}$('.commentlist li').each(function(i){$(this).prepend('<span class="co-number">'+(i+1)+'<\/span>');})});
//]]>
</script>
Der Schnippsel steht im Footer oder wird extern geladen, benötigt jQuery.
Danke für den Code! War genau das, wonach ich gesucht habe.
Grüße
Christian