Kommentare und Pings im WordPress-Theme getrennt zählen und anzeigen

Statt alle Reaktionen auf einen Beitrag – also Kommentare, Trackbacks und Pingbacks – gemeinsam in einer Liste anzuzeigen, trenne ich der Übersichtlichkeit halber gerne Kommentare und Pings (Pingbacks und Trackbacks) voneinander. An sich ist das auch nicht sonderlich schwer, es gibt aber ein paar Dinge zu beachten.

Das Problem (bei meiner bisherigen Lösung)

Der vermutlich offensichtlichste und von mir bis vor Kurzem zur Trennung genutzte Weg ist der folgende Aufruf des Kommentar-Templates:

comments_template( '', true );

Der zweite Parameter ist nämlich dafür zuständig, dass die Reaktionen nach Typ getrennt werden und über die $comments_by_type-Variable in der comments.php genutzt werden können – die Nummer der Kommentare habe ich dann immer über count( $comments_by_type['comment'] ) ermittelt. Das funktioniert auch wunderbar, solange die Kommentare und Pings nicht in mehrere Seiten umgebrochen werden. Wenn das der Fall ist, würde das Ergebnis des count()-Aufrufs von oben nur die Zahl der Kommentare auf der aktuellen Seite anzeigen – nicht die Anzahl aller Kommentare.

Die Lösung

Die Lösung ist, die Reaktionen in der comments.php selbst zu holen und auf den zweiten Parameter bei dem comments_template()-Aufruf zu verzichten. Zur Veranschaulichung, wie das beispielsweise aussehen kann, gehe ich hier die gesamte comments.php meines neuesten Themes durch.

<?php
/**
 * Comments template.
 *
 * @version 1.0.0
 *
 * @package Photographus
 */

if ( post_password_required() ) {
	return;
} ?>
<aside aria-labelledby="aside" class="comments-area">
	<?php if ( have_comments() ) {
		/**
		 * We cannot use the second parameter from comments_template()
		 * to separate the reactions because if they are
		 * broken on multiple pages, the count() would only return
		 * the number of comments and pings which are displayed
		 * on the current page, not the total.
		 *
		 * Because of that, we use our own function to get the comments by type.
		 */
		$comments_by_type = photographus_get_comments_by_type();

Nachdem wir mit post_password_required() geprüft haben, ob der Beitrag passwortgeschützt ist und nicht das korrekte Passwort eingegeben wurde, prüfen wir mit have_comments() auf Reaktionen zu dem Beitrag. Danach holen wir uns – wie eben schon kurz angesprochen – über eine eigene Funktion die Reaktionen zum Beitrag (bereits in separierter Form). Die entsprechende Funktion kommt in die functions.php (oder in meinem Fall die template-tags.php) und sieht so aus:

/**
 * Returns the post reactions separated by type.
 *
 * @return array Post reactions separated by type.
 */
function photographus_get_comments_by_type() {
	$comment_args     = [
		'order'   => 'ASC',
		'orderby' => 'comment_date_gmt',
		'status'  => 'approve',
		'post_id' => get_the_ID(),
	];
	$comments         = get_comments( $comment_args );
	$comments_by_type = separate_comments( $comments );

	return $comments_by_type;
}

Zuerst bauen wir uns ein Argument-Array, um die genehmigten Beitrags-Reaktionen nach Datum aufsteigend sortiert zu erhalten. Danach holen wir uns mit get_comments() die Reaktionen und separieren sie über separate_comments(). Danach wird das Ergebnis zurückgegeben.

Weiter geht es in der comments.php mit der Anzeige der Kommentaranzahl und Kommentarliste:

if ( ! empty( $comments_by_type['comment'] ) ) {
	/**
	 * Save the comment count.
	 */
	$comment_number = count( $comments_by_type['comment'] ); ?>
	<h2 class="comments-title" id="comments-title">
		<?php printf( /* translators: Title for comment list. 1=comment number, 2=post title */
			_n(
				'%1$s Comment on “%2$s”',
				'%1$s Comments on “%2$s”',
				$comment_number,
				'photographus'
			),
			number_format_i18n( $comment_number ),
			get_the_title() ); ?>
	</h2>

	<ul class="commentlist">
		<?php
		/**
		 * We need to specify the per_page key because otherwise
		 * the separated reactions would not be broken correctly into
		 * multiple pages.
		 */
		wp_list_comments( [
			'callback' => 'photographus_comments',
			'style'    => 'ul',
			'type'     => 'comment',
			'per_page' => $comment_args['number'],
		] ); ?>
	</ul>
<?php }

Zunächst gehen wir sicher, dass wir überhaupt Kommentare haben und speichern danach die Anzahl. Diese geben wir anschließend in einer h2-Überschrift aus und nutzen dafür die _n()-Funktion, die folgende Parameter erwartet:

  1. Singularform des Strings.
  2. Pluralform.
  3. Nummer, anhand derer Singular oder Plural angezeigt wird.
  4. Text-Domain.

Als ungeordnete Liste zeigen wir danach die Kommentare an und übergeben an wp_list_comments() ein Array mit den folgenden Argumenten:

  • photographus_comments als callback-Funktion zur Anzeige der Kommentare. Da die Angabe eines Callbacks optional ist, werde ich hier jetzt nicht auf die photographus_comments() eingehen – anschauen könnt ihr sie euch in der Code-Referenz.
  • ul als style der Liste.
  • comment als type, damit nur die Kommentare angezeigt werden.
  • $comment_args['number'] als Wert für den per_page-Schlüssel, damit die richtige Zahl angezeigt wird, wenn die Reaktionen auf mehrere Seiten umgebrochen werden sollen. Ohne diese Angabe würde beispielsweise, wenn zehn Kommentare pro Seite angezeigt werden sollen, fünf Kommentare und fünf Pings angezeigt werden – nicht jeweils zehn.

Die Zählung und Anzeige der Pings sieht ähnlich aus:

if ( ! empty( $comments_by_type['pings'] ) ) {
	/**
	 * Save the count of trackbacks and pingbacks.
	 */
	$trackback_number = count( $comments_by_type['pings'] ); ?>
	<h2 class="trackbacks-title" id="trackbacks-title">
		<?php printf( /* translators: Title for trackback list. 1=trackback number, 2=post title */
			_n(
				'%1$s Trackback on “%2$s”',
				'%1$s Trackbacks on “%2$s”',
				$trackback_number,
				'photographus'
			),
			number_format_i18n( $trackback_number ),
			get_the_title() ); ?>
	</h2>

	<ul class="commentlist">
		<?php
		/**
		 * Display the pings in short version.
		 */
		wp_list_comments( [
			'type'       => 'pings',
			'short_ping' => true,
			'per_page'   => $comment_args['number'],
		] ); ?>
	</ul>
<?php }

Theoretisch könnten wir auch noch die Pingbacks und Trackbacks trennen, indem wir nicht $comments_by_type['pings'] nutzen, sondern $comments_by_type['pingback'] und $comments_by_type['trackback'].

Kommen wir zum letzten Teil:

		/**
		 * Only show the comments navigation if one of the reaction counts
		 * is larger than the set number of comments per page. Necessary because
		 * of our separation. Otherwise, the navigation would also be displayed if
		 * we should display 4 comments per page and have 3 comments and 2 trackbacks.
		 */
		if ( ( isset( $trackback_number ) && $trackback_number > $comment_args['number'] ) || ( isset( $comment_number ) && $comment_number > $comment_args['number'] ) ) {
			the_comments_navigation();
		}

		/**
		 * Display comments closed hint if comments are closed but we already have comments.
		 */
		if ( ! comments_open() && get_comments_number() ) { ?>
			<p class="nocomments"><?php _e( 'Comments are closed.', 'photographus' ); ?></p>
		<?php }
	} // End if().

	/**
	 * Display comment form with modified submit label.
	 */
	comment_form( [
		'label_submit' => __( 'Submit Comment', 'photographus' ),
	] ); ?>
</aside>

Wir prüfen zunächst ob Kommentare oder Pings in höherer Zahl vorhanden sind als die eingestellte Anzahl pro Seite, und geben in diesem Fall die Kommentar-Navigation aus. Danach zeigen wir gegebenenfalls noch einen Hinweis für geschlossene Kommentare sowie das Kommentar-Formular an.

Abschließend hier noch die gesamte comments.php:

<?php
/**
 * Comments template.
 *
 * @version 1.0.0
 *
 * @package Photographus
 */

if ( post_password_required() ) {
	return;
} ?>
<aside aria-labelledby="aside" class="comments-area">
	<?php if ( have_comments() ) {
		/**
		 * We cannot use the second parameter from comments_template()
		 * to separate the reactions because if they are
		 * broken on multiple pages, the count() would only return
		 * the number of comments and pings which are displayed
		 * on the current page, not the total.
		 *
		 * Because of that, we use our own function to get the comments by type.
		 */
		$comments_by_type = photographus_get_comments_by_type();
		if ( ! empty( $comments_by_type['comment'] ) ) {
			/**
			 * Save the comment count.
			 */
			$comment_number = count( $comments_by_type['comment'] ); ?>
			<h2 class="comments-title" id="comments-title">
				<?php printf( /* translators: Title for comment list. 1=comment number, 2=post title */
					_n(
						'%1$s Comment on “%2$s”',
						'%1$s Comments on “%2$s”',
						$comment_number,
						'photographus'
					),
					number_format_i18n( $comment_number ),
					get_the_title() ); ?>
			</h2>

			<ul class="commentlist">
				<?php
				/**
				 * We need to specify the per_page key because otherwise
				 * the separated reactions would not be broken correctly into
				 * multiple pages.
				 */
				wp_list_comments( [
					'callback' => 'photographus_comments',
					'style'    => 'ul',
					'type'     => 'comment',
					'per_page' => $comment_args['number'],
				] ); ?>
			</ul>
		<?php }
		if ( ! empty( $comments_by_type['pings'] ) ) {
			/**
			 * Save the count of trackbacks and pingbacks.
			 */
			$trackback_number = count( $comments_by_type['pings'] ); ?>
			<h2 class="trackbacks-title" id="trackbacks-title">
				<?php printf( /* translators: Title for trackback list. 1=trackback number, 2=post title */
					_n(
						'%1$s Trackback on “%2$s”',
						'%1$s Trackbacks on “%2$s”',
						$trackback_number,
						'photographus'
					),
					number_format_i18n( $trackback_number ),
					get_the_title() ); ?>
			</h2>

			<ul class="commentlist">
				<?php
				/**
				 * Display the pings in short version.
				 */
				wp_list_comments( [
					'type'       => 'pings',
					'short_ping' => true,
					'per_page'   => $comment_args['number'],
				] ); ?>
			</ul>
		<?php }
		/**
		 * Only show the comments navigation if one of the reaction counts
		 * is larger than the set number of comments per page. Necessary because
		 * of our separation. Otherwise, the navigation would also be displayed if
		 * we should display 4 comments per page and have 3 comments and 2 trackbacks.
		 */
		if ( ( isset( $trackback_number ) && $trackback_number > $comment_args['number'] ) || ( isset( $comment_number ) && $comment_number > $comment_args['number'] ) ) {
			the_comments_navigation();
		}

		/**
		 * Display comments closed hint if comments are closed but we already have comments.
		 */
		if ( ! comments_open() && get_comments_number() ) { ?>
			<p class="nocomments"><?php _e( 'Comments are closed.', 'photographus' ); ?></p>
		<?php }
	} // End if().

	/**
	 * Display comment form with modified submit label.
	 */
	comment_form( [
		'label_submit' => __( 'Submit Comment', 'photographus' ),
	] ); ?>
</aside>

Das könnte auch interessant sein

Schreib einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.