WordPress как на ладони

wp_list_comments()WP 2.7.0

Выводит комментарии записей (постов, страниц). Функция может принимать ряд параметров и используется в шаблоне для вывода списка комментариев к посту/странице. Некоторые из параметров можно настроить в админ-панели.

Эта функция сама по себе ничего не делает. Она должна быть вызвана из файла шаблона комментариев, например, comments.php, который в свою очередь должен быть подключен функцией comments_template().

Рассмотрим на примере:

Файл страницы/поста, в который вы хотите вставить комментарии:

<?php comments_template( '/comments.php' ); ?>

Затем, в файле comments.php:

<div>
	<?php wp_list_comments(); ?>
</div>

Почему нужно делать именно так? Перед этой функцией должна быть вызвана функция comments_template(). Она получает из базы данных комментарии для вывода, которые затем использует эта функция. Если этого не сделать, то нужно указать второй параметр $comments, где указать комментарии которые мы хотим вывести.

Хуки из функции

Возвращает

null|Строку. HTML списка комментариев, когда параметр echo=1. Null, когда параметр echo=0.

Шаблон использования

<ul class="commentlist">
	<?php
	wp_list_comments( [
		'walker'            => null,
		'max_depth'         => '',
		'style'             => 'ul',
		'callback'          => null,
		'end-callback'      => null,
		'type'              => 'all',
		'reply_text'        => 'Reply',
		'page'              => '',
		'per_page'          => '',
		'avatar_size'       => 32,
		'reverse_top_level' => null,
		'reverse_children'  => '',
		'format'            => 'html5', // или xhtml, если HTML5 не поддерживается темой
		'short_ping'        => false,    // С версии 3.6,
		'echo'              => true,     // true или false
	] );
	?>
</ul>

Использование

<?php wp_list_comments( $args, $comments ); ?>
$args(строка/массив)
Массив аргументов, определяющий вывод комментариев.
По умолчанию: параметры по умолчанию
$comments(массив)
Массив полученный функцией get_comments().
По умолчанию: $wp_query->comments

Аргументы параметра $args

walker(объект)
Экземпляр класса, на основе которого собирается список комментариев. По умолчанию за вывод отвечает класс Walker_Comment.
По умолчанию: null (new Walker_Comment)
max_depth(число)
Глубина вложенности дочерних комментариев. Работает если включена поддержка древовидных комментариев. Параметр устанавливается в админ-панели.
По умолчанию: 5
style(строка)

В каком виде выводить список комментариев. Может быть div, ol или ul. Имейте ввиду, что сам список нужно оборачивать вручную:

<div class="commentlist">
 <?php wp_list_comments(array('style' => 'div')); ?>
</div>

или

<ol class="commentlist">
  <?php wp_list_comments(array('style' => 'ol')); ?>
</ol>

По умолчанию: 'ol'

callback(строка)

Название функции, которая будет формировать HTML вывод каждого комментария.

Указанная тут функция будет вызываться при выводе каждого комментария. Имейте ввиду, что функция должна содержать открывающий тег <div> или <li> (в зависимости от параметра style), но этот тег не должен закрываться. WordPress впишет закрывающий тег автоматически. Можно использовать параметр end-callback, чтобы изменить его.

Такое разделение нужно для древовидных комментариев, когда один коммент вложен в другой.

Функция получит три параметра $comment, $args, $depth. По умолчанию вызывается метод:

По умолчанию: null

end-callback(строка)

Название функции, которая будет формировать HTML вывод закрытия каждого комментария.

Указанная тут функция будет вызываться при закрытии каждого комментария. Она должна выводить закрывающий тег </div> или </li> (в зависимости от параметра style).

Параметры callback и end-callback разделены, для того чтобы правильно выводить древовидные комментарии.

По умолчанию: null

type(строка)
Какой тип комментариев показывать. Может быть all, comment, trackback, pingback или pings. pings включает в себя 'trackback' и 'pingback'.
По умолчанию: all
per_page(число)

Количество комментариев на странице. Работа этого параметра не так проста:

  • Если параметры page или per_page переданы и они не равны тем что указаны в $wp_query: get_query_var('cpage') и get_query_var('comments_per_page'), то будет создан отдельный запрос на получение всех комментов текущей записи и комментарии будут разделены на страницы пагинации.

  • Если указать пустую строку '' и опция get_option( 'page_comments' ) включена, то этот параметр будет равен опции get_query_var( 'comments_per_page' ).

  • Если параметр пустой (empty), то параметры per_page и page выставятся в 0;

Таким образом, когда нужно вывести все комментарии (без разбивки на страницы пагинации) указывает параметр: per_page=0 и page=1.

По умолчанию: 50

page(число)
Страница пагинации, комментарии которой нужно вывести.
avatar_size(число)
Размер аватара в пикселях.
По умолчанию: 32
reverse_top_level(логический)
Если поставить true (1), то самые последние комментарии будут наверху (обратная сортировка по дате). Влияет только на комментарии верхнего уровня (родительские, те у которых есть или могут быть дочерние комменты).
По умолчанию: false
reverse_children(логический)
Если поставить true, то самые последние комментарии будут наверху (обратная сортировка по дате). Влияет только на дочерние комментарии.
По умолчанию: false
reply_text(строка)
Текст, который нужно показать в ссылке "ответить". Текст используется в функции: get_comment_reply_link().
По умолчанию: 'reply'
login_text(строка)
Текст, который будет показан для не зарегистрированных пользователей, если комменты могут оставлять только зарегистрированные юзеры.
По умолчанию: 'Log in to Reply'
echo(логический)
Выводить код на экран или возвращать для обработки.
По умолчанию: 'true'

Примеры

1

#1 Вывод комментариев с использованием пользовательской функции

Для настройки внешнего вида каждого комментария, можно использовать параметр callback в который указать название функции, а затем создать эту функцию с нужным кодом (выводом):

<ul class="commentlist">
	  <?php wp_list_comments('type=comment&callback=mytheme_comment'); ?>
</ul>

Мы выводим список комментариев (type=comment), т.е. это не пинги, а так же используем свою функцию формирующую внешний вид комментария (callback=mytheme_comment). Функцию mytheme_comment нужно описывать отдельно, можно в файл functions.php или прям в том же файле, где находится этот код (обычно это comments.php).

<?php
function mytheme_comment( $comment, $args, $depth ) {
	if ( 'div' === $args['style'] ) {
		$tag       = 'div';
		$add_below = 'comment';
	} else {
		$tag       = 'li';
		$add_below = 'div-comment';
	}

	$classes = ' ' . comment_class( empty( $args['has_children'] ) ? '' : 'parent', null, null, false );
	?>

	<<?php echo $tag, $classes; ?> id="comment-<?php comment_ID() ?>">
	<?php if ( 'div' != $args['style'] ) { ?>
		<div id="div-comment-<?php comment_ID() ?>" class="comment-body"><?php
	} ?>

	<div class="comment-author vcard">
		<?php
		if ( $args['avatar_size'] != 0 ) {
			echo get_avatar( $comment, $args['avatar_size'] );
		}
		printf(
			__( '<cite class="fn">%s</cite> <span class="says">says:</span>' ),
			get_comment_author_link()
		);
		?>
	</div>

	<?php if ( $comment->comment_approved == '0' ) { ?>
		<em class="comment-awaiting-moderation">
			<?php _e( 'Your comment is awaiting moderation.' ); ?>
		</em><br/>
	<?php } ?>

	<div class="comment-meta commentmetadata">
		<a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ); ?>">
			<?php
			printf(
				__( '%1$s at %2$s' ),
				get_comment_date(),
				get_comment_time()
			); ?>
		</a>

		<?php edit_comment_link( __( '(Edit)' ), '  ', '' ); ?>
	</div>

	<?php comment_text(); ?>

	<div class="reply">
		<?php
		comment_reply_link(
			array_merge(
				$args,
				array(
					'add_below' => $add_below,
					'depth'     => $depth,
					'max_depth' => $args['max_depth']
				)
			)
		); ?>
	</div>

	<?php if ( 'div' != $args['style'] ) { ?>
		</div>
	<?php }
}

callback функция содержит только открывающий тег <li> и он не должен закрываться. Подробнее см. в описании параметра.

0

#2 Использование по умолчанию

Выводит список комментариев. Используется в файле шаблона comments.php. Наличие древовидности и пагинации у комментариев контролируется через админ-панель Опции->Обсуждение.

<ol class="commentlist">
	<?php wp_list_comments(); ?>
</ol>
0

#3 Вывод комментариев для определенного поста

Если нужно вывести привычный список комментариев, но при этом в этот список должны попасть только нужные комментарии. Допустим, нам нужно вывести комментарии определенного поста. Для этого сначала получим нужные комментарии, а затем передадим их во второй параметр функции wp_list_comments(), чтобы вывести их в привычном формате. Древовидность, если она установлена, сохраняется.

<ol class="commentlist">
	<?php
		// Получаем комментарии поста с ID XXX из базы данных 
		$comments = get_comments(array(
			'post_id' => XXX,
			'status' => 'approve' // комментарии прошедшие модерацию
		));

		// Формируем вывод списка полученных комментариев
		wp_list_comments(array(
			'per_page' => 10, // Пагинация комментариев - по 10 на страницу
			'reverse_top_level' => false // Показываем последние комментарии в начале
		), $comments);
	?>
</ol>
0

#4 Пример использования параметра walker и создание своего класса

Пример файла comments.php:

<?php
if ( post_password_required() ) {
	return;
}

if ( $comments ) {
	?>

	<div class="comments" id="comments">

		<?php
		wp_list_comments(
			array(
				'walker'      => new TwentyTwenty_Walker_Comment(),
				'avatar_size' => 120,
				'style'       => 'div',
			)
		);
		?>

	</div><!-- comments -->

	<?php
}

Класс Волкера

<?php

/**
 * CUSTOM COMMENT WALKER
 * A custom walker for comments, based on the walker in Twenty Nineteen.
 *
 * @since Twenty Twenty 1.0
 */
class TwentyTwenty_Walker_Comment extends Walker_Comment {

	/**
	 * Outputs a comment in the HTML5 format.
	 *
	 * @since Twenty Twenty 1.0
	 *
	 * @see wp_list_comments()
	 * @see https://developer.wordpress.org/reference/functions/get_comment_author_url/
	 * @see https://developer.wordpress.org/reference/functions/get_comment_author/
	 * @see https://developer.wordpress.org/reference/functions/get_avatar/
	 * @see https://developer.wordpress.org/reference/functions/get_comment_reply_link/
	 * @see https://developer.wordpress.org/reference/functions/get_edit_comment_link/
	 *
	 * @param WP_Comment $comment Comment to display.
	 * @param int        $depth   Depth of the current comment.
	 * @param array      $args    An array of arguments.
	 */
	protected function html5_comment( $comment, $depth, $args ) {

		$tag = ( 'div' === $args['style'] ) ? 'div' : 'li';

		?>
		<<?php echo $tag; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static output ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( $this->has_children ? 'parent' : '', $comment ); ?>>
			<article id="div-comment-<?php comment_ID(); ?>" class="comment-body">
				<footer class="comment-meta">
					<div class="comment-author vcard">
						<?php
						$comment_author_url = get_comment_author_url( $comment );
						$comment_author     = get_comment_author( $comment );
						$avatar             = get_avatar( $comment, $args['avatar_size'] );
						if ( 0 !== $args['avatar_size'] ) {
							if ( empty( $comment_author_url ) ) {
								echo wp_kses_post( $avatar );
							} else {
								printf( '<a href="%s" rel="external nofollow" class="url">', $comment_author_url ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped --Escaped in https://developer.wordpress.org/reference/functions/get_comment_author_url/
								echo wp_kses_post( $avatar );
							}
						}

						printf(
							'<span class="fn">%1$s</span><span class="screen-reader-text says">%2$s</span>',
							esc_html( $comment_author ),
							__( 'says:', 'twentytwenty' )
						);

						if ( ! empty( $comment_author_url ) ) {
							echo '</a>';
						}
						?>
					</div><!-- .comment-author -->

					<div class="comment-metadata">
						<?php
						/* translators: 1: Comment date, 2: Comment time. */
						$comment_timestamp = sprintf( __( '%1$s at %2$s', 'twentytwenty' ), get_comment_date( '', $comment ), get_comment_time() );

						printf(
							'<a href="%s"><time datetime="%s" title="%s">%s</time></a>',
							esc_url( get_comment_link( $comment, $args ) ),
							get_comment_time( 'c' ),
							esc_attr( $comment_timestamp ),
							esc_html( $comment_timestamp )
						);

						if ( get_edit_comment_link() ) {
							printf(
								' <span aria-hidden="true">•</span> <a class="comment-edit-link" href="%s">%s</a>',
								esc_url( get_edit_comment_link() ),
								__( 'Edit', 'twentytwenty' )
							);
						}
						?>
					</div><!-- .comment-metadata -->

				</footer><!-- .comment-meta -->

				<div class="comment-content entry-content">

					<?php

					comment_text();

					if ( '0' === $comment->comment_approved ) {
						?>
						<p class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'twentytwenty' ); ?></p>
						<?php
					}

					?>

				</div><!-- .comment-content -->

				<?php

				$comment_reply_link = get_comment_reply_link(
					array_merge(
						$args,
						array(
							'add_below' => 'div-comment',
							'depth'     => $depth,
							'max_depth' => $args['max_depth'],
							'before'    => '<span class="comment-reply">',
							'after'     => '</span>',
						)
					)
				);

				$by_post_author = twentytwenty_is_comment_by_post_author( $comment );

				if ( $comment_reply_link || $by_post_author ) {
					?>

					<footer class="comment-footer-meta">

						<?php
						if ( $comment_reply_link ) {
							echo $comment_reply_link; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Link is escaped in https://developer.wordpress.org/reference/functions/get_comment_reply_link/
						}
						if ( $by_post_author ) {
							echo '<span class="by-post-author">' . __( 'By Post Author', 'twentytwenty' ) . '</span>';
						}
						?>

					</footer>

					<?php
				}
				?>

			</article><!-- .comment-body -->

		<?php
	}
}

Заметки

  • Смотрите: WP_Query::$comments
  • Global. WP_Query. $wp_query WordPress Query object.
  • Global. int. $comment_alt
  • Global. int. $comment_depth
  • Global. int. $comment_thread_alt
  • Global. true|false. $overridden_cpage
  • Global. true|false. $in_comment_loop

Список изменений

С версии 2.7.0 Введена.

Код wp_list_comments() WP 6.1.1

function wp_list_comments( $args = array(), $comments = null ) {
	global $wp_query, $comment_alt, $comment_depth, $comment_thread_alt, $overridden_cpage, $in_comment_loop;

	$in_comment_loop = true;

	$comment_alt        = 0;
	$comment_thread_alt = 0;
	$comment_depth      = 1;

	$defaults = array(
		'walker'            => null,
		'max_depth'         => '',
		'style'             => 'ul',
		'callback'          => null,
		'end-callback'      => null,
		'type'              => 'all',
		'page'              => '',
		'per_page'          => '',
		'avatar_size'       => 32,
		'reverse_top_level' => null,
		'reverse_children'  => '',
		'format'            => current_theme_supports( 'html5', 'comment-list' ) ? 'html5' : 'xhtml',
		'short_ping'        => false,
		'echo'              => true,
	);

	$parsed_args = wp_parse_args( $args, $defaults );

	/**
	 * Filters the arguments used in retrieving the comment list.
	 *
	 * @since 4.0.0
	 *
	 * @see wp_list_comments()
	 *
	 * @param array $parsed_args An array of arguments for displaying comments.
	 */
	$parsed_args = apply_filters( 'wp_list_comments_args', $parsed_args );

	// Figure out what comments we'll be looping through ($_comments).
	if ( null !== $comments ) {
		$comments = (array) $comments;
		if ( empty( $comments ) ) {
			return;
		}
		if ( 'all' !== $parsed_args['type'] ) {
			$comments_by_type = separate_comments( $comments );
			if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
				return;
			}
			$_comments = $comments_by_type[ $parsed_args['type'] ];
		} else {
			$_comments = $comments;
		}
	} else {
		/*
		 * If 'page' or 'per_page' has been passed, and does not match what's in $wp_query,
		 * perform a separate comment query and allow Walker_Comment to paginate.
		 */
		if ( $parsed_args['page'] || $parsed_args['per_page'] ) {
			$current_cpage = get_query_var( 'cpage' );
			if ( ! $current_cpage ) {
				$current_cpage = 'newest' === get_option( 'default_comments_page' ) ? 1 : $wp_query->max_num_comment_pages;
			}

			$current_per_page = get_query_var( 'comments_per_page' );
			if ( $parsed_args['page'] != $current_cpage || $parsed_args['per_page'] != $current_per_page ) {
				$comment_args = array(
					'post_id' => get_the_ID(),
					'orderby' => 'comment_date_gmt',
					'order'   => 'ASC',
					'status'  => 'approve',
				);

				if ( is_user_logged_in() ) {
					$comment_args['include_unapproved'] = array( get_current_user_id() );
				} else {
					$unapproved_email = wp_get_unapproved_comment_author_email();

					if ( $unapproved_email ) {
						$comment_args['include_unapproved'] = array( $unapproved_email );
					}
				}

				$comments = get_comments( $comment_args );

				if ( 'all' !== $parsed_args['type'] ) {
					$comments_by_type = separate_comments( $comments );
					if ( empty( $comments_by_type[ $parsed_args['type'] ] ) ) {
						return;
					}

					$_comments = $comments_by_type[ $parsed_args['type'] ];
				} else {
					$_comments = $comments;
				}
			}

			// Otherwise, fall back on the comments from `$wp_query->comments`.
		} else {
			if ( empty( $wp_query->comments ) ) {
				return;
			}
			if ( 'all' !== $parsed_args['type'] ) {
				if ( empty( $wp_query->comments_by_type ) ) {
					$wp_query->comments_by_type = separate_comments( $wp_query->comments );
				}
				if ( empty( $wp_query->comments_by_type[ $parsed_args['type'] ] ) ) {
					return;
				}
				$_comments = $wp_query->comments_by_type[ $parsed_args['type'] ];
			} else {
				$_comments = $wp_query->comments;
			}

			if ( $wp_query->max_num_comment_pages ) {
				$default_comments_page = get_option( 'default_comments_page' );
				$cpage                 = get_query_var( 'cpage' );
				if ( 'newest' === $default_comments_page ) {
					$parsed_args['cpage'] = $cpage;

					/*
					* When first page shows oldest comments, post permalink is the same as
					* the comment permalink.
					*/
				} elseif ( 1 == $cpage ) {
					$parsed_args['cpage'] = '';
				} else {
					$parsed_args['cpage'] = $cpage;
				}

				$parsed_args['page']     = 0;
				$parsed_args['per_page'] = 0;
			}
		}
	}

	if ( '' === $parsed_args['per_page'] && get_option( 'page_comments' ) ) {
		$parsed_args['per_page'] = get_query_var( 'comments_per_page' );
	}

	if ( empty( $parsed_args['per_page'] ) ) {
		$parsed_args['per_page'] = 0;
		$parsed_args['page']     = 0;
	}

	if ( '' === $parsed_args['max_depth'] ) {
		if ( get_option( 'thread_comments' ) ) {
			$parsed_args['max_depth'] = get_option( 'thread_comments_depth' );
		} else {
			$parsed_args['max_depth'] = -1;
		}
	}

	if ( '' === $parsed_args['page'] ) {
		if ( empty( $overridden_cpage ) ) {
			$parsed_args['page'] = get_query_var( 'cpage' );
		} else {
			$threaded            = ( -1 != $parsed_args['max_depth'] );
			$parsed_args['page'] = ( 'newest' === get_option( 'default_comments_page' ) ) ? get_comment_pages_count( $_comments, $parsed_args['per_page'], $threaded ) : 1;
			set_query_var( 'cpage', $parsed_args['page'] );
		}
	}
	// Validation check.
	$parsed_args['page'] = (int) $parsed_args['page'];
	if ( 0 == $parsed_args['page'] && 0 != $parsed_args['per_page'] ) {
		$parsed_args['page'] = 1;
	}

	if ( null === $parsed_args['reverse_top_level'] ) {
		$parsed_args['reverse_top_level'] = ( 'desc' === get_option( 'comment_order' ) );
	}

	wp_queue_comments_for_comment_meta_lazyload( $_comments );

	if ( empty( $parsed_args['walker'] ) ) {
		$walker = new Walker_Comment;
	} else {
		$walker = $parsed_args['walker'];
	}

	$output = $walker->paged_walk( $_comments, $parsed_args['max_depth'], $parsed_args['page'], $parsed_args['per_page'], $parsed_args );

	$in_comment_loop = false;

	if ( $parsed_args['echo'] ) {
		echo $output;
	} else {
		return $output;
	}
}
56 комментариев
Полезные 5 Вопросы 1 Все
    Войти