wp_list_comments()
Outputs comments of posts (posts, pages). The function can accept a number of parameters and is used in the template to display a list of comments for a post/page. Some parameters can be configured in the admin panel.
This function itself does nothing. It should be called from the comments template file, for example, comments.php, which in turn should be included by the function comments_template().
Let's consider an example:
The file of the page/post where you want to insert comments:
<?php comments_template( '/comments.php' ); ?>
Then, in the comments.php file:
<div> <?php wp_list_comments(); ?> </div>
Why should it be done this way? The function comments_template() must be called before this function. It retrieves comments from the database for output, which this function then uses. If this is not done, the second parameter $comments must be specified, where you indicate the comments you want to display.
Hooks from the function
Returns
null|String. HTML list of comments when the parameter echo=1. Null when the parameter echo=0.
Usage Template
<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', // or xhtml if HTML5 is not supported by the theme 'short_ping' => false, // Since version 3.6, 'echo' => true, // true or false ] ); ?> </ul>
Usage
<?php wp_list_comments( $args, $comments ); ?>
- $args(string/array)
- Array of arguments that defines the output of comments.
Default: default parameters - $comments(array)
- Array obtained from the function get_comments().
Default: $wp_query->comments
Arguments of the $args parameter
- walker(object)
- Instance of the class on which the list of comments is built. By default, the output is handled by the class Walker_Comment.
Default: null (new Walker_Comment) - max_depth(number)
- The depth of nested child comments. Works if support for threaded comments is enabled. The parameter is set in the admin panel.
Default: 5 - style(string)
How to display the list of comments. Can be div, ol, or ul. Keep in mind that the list itself needs to be wrapped manually:
<div class="commentlist"> <?php wp_list_comments(array('style' => 'div')); ?> </div>or
<ol class="commentlist"> <?php wp_list_comments(array('style' => 'ol')); ?> </ol>Default: 'ol'
- callback(string)
Name of the function that will generate the HTML output of each comment.
The specified function will be called when outputting each comment. Keep in mind that the function must contain an opening tag <div> or <li> (depending on the style parameter), but this tag should not be closed. WordPress will automatically insert the closing tag. You can use the
end-callbackparameter to change it.This separation is needed for threaded comments, where one comment is nested within another.
The function will receive three parameters
$comment, $args, $depth. By default, the method is called:- for pingback or trackback comment types - Walker_Comment::ping().
- when
format = html5- Walker_Comment::html5_comment(). - when
format != html5- Walker_Comment::comment().
Default: null
- end-callback(string)
Name of the function that will generate the HTML output for closing each comment.
The specified function will be called when closing each comment. It should output the closing tag </div> or </li> (depending on the style parameter).
The
callbackandend-callbackparameters are separated to correctly output threaded comments.Default: null
- type(string)
- What type of comments to show. Can be all, comment, trackback, pingback, or
pings. pings includes 'trackback' and 'pingback'.
Default: all - per_page(number)
Number of comments per page. The operation of this parameter is not so straightforward:
-
If the parameters
pageorper_pageare passed and they are not equal to those specified in $wp_query: get_query_var('cpage') and get_query_var('comments_per_page'), a separate query will be created to retrieve all comments of the current post, and comments will be paginated. -
If an empty string '' is specified and the option get_option( 'page_comments' ) is enabled, this parameter will equal the option get_query_var( 'comments_per_page' ).
- If the parameter is empty (empty), then the parameters per_page and page will be set to 0;
Thus, when you need to display all comments (without pagination), specify the parameter: per_page=0 and page=1.
Default: 50
-
- page(number)
- Page of pagination whose comments need to be displayed.
- avatar_size(number)
- Size of the avatar in pixels.
Default: 32 - reverse_top_level(boolean)
- If set to true (1), the most recent comments will be at the top (reverse sorting by date). Affects only top-level comments (parent comments that have or can have child comments).
Default: false - reverse_children(boolean)
- If set to true, the most recent comments will be at the top (reverse sorting by date). Affects only child comments.
Default: false - reply_text(string)
- Text to be shown in the "reply" link. The text is used in the function: get_comment_reply_link().
Default: 'reply' - login_text(string)
- Text that will be shown for unregistered users if comments can only be left by registered users.
Default: 'Log in to Reply' - echo(boolean)
- Output the code to the screen or return it for processing.
Default: 'true'
Examples
#1 Example of using the walker parameter and creating your own class
An example of a comments.php file:
<?php
if ( post_password_required() ) {
return;
}
if ( $comments ) {
?>
<div class="comments" id="comments">
<?php
wp_list_comments( [
'walker' => new TwentyTwenty_Walker_Comment(),
'avatar_size' => 120,
'style' => 'div',
] );
?>
</div><!-- comments -->
<?php
}
Walker Class:
<?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';
?>
<<?= $tag ?> 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
}
} #2 Comment output using a custom function
To customize the appearance of each comment, you can use the callback parameter in which you specify the name of the function and then create that function with the desired code (output):
<ul class="commentlist"> <?php wp_list_comments( [ 'type' => 'comment', 'callback' => 'mytheme_comment', ] ); ?> </ul>
We display a list of comments -- type=comment -- i.e. they are not pings, and we also use our function that forms the appearance of the comment -- callback=mytheme_comment. Function mytheme_comment() should be described separately, you can add it in the file functions.php or directly in the same file where this code is located (usually it is 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 );
?>
<<?= $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 }
}
IMPORTANT: the callback function must contain only the opening tag <li> and it must not be closed. See parameter description for details.
#3 Default use
Displays a list of comments. It is used in the comments.php template file. The presence of tree view and pagination in comments is controlled through the admin panel Settings > Discussion.
<ol class="commentlist"> <?php wp_list_comments(); ?> </ol>
Or customizing using parameters:
$cpage = get_query_var( 'cpage' ) ? get_query_var( 'cpage' ) : 1; wp_list_comments( [ 'avatar_size' => 60, 'short_ping' => true, 'type' => 'comment', 'callback' => 'ic_comment_list', 'per_page' => get_option( 'comments_per_page' ), 'page' => $cpage, 'reverse_top_level' => get_option( 'default_comments_page' ) === 'oldest' ? false : true, ] );
#4 Display comments for a specific post
If you want to display the usual list of comments, but this list should include only the necessary comments.
Let's say we need to output the comments of a certain post. To do that, we'll first get the comments we want and then pass them to the second parameter of wp_list_comments() to output them in the usual format. The tree view, if set, is preserved.
<ol class="commentlist"> <?php // Retrieve post comments with ID XXX from the database $comments = get_comments( [ 'post_id' => XXX, 'status' => 'approve' // moderated comments ] ); // generate a list of received comments wp_list_comments( [ 'per_page' => 10, // Pagination of comments - 10 per page 'reverse_top_level' => false // Show last comments at the beginning ], $comments ); ?> </ol>
#5 “Comment is awaiting moderation” alert.
If you are using WordPress 4.9.6 or higher and not showing “Comment is awaiting moderation” alert.
You can follow the steps below.
- Settings > Discussion > enable “Show comments cookies opt-in checkbox.”
- After activating checkbox will show on comments form like this. “Save my name, email, and website in this browser for the next time I comment.”
That’s it.
If you want to customize this checkbox field, you can use this code.
$comment_form = array( 'fields' => array( 'cookies' => '<p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"' . $consent . ' />' . '<label for="wp-comment-cookies-consent">' . __( 'Save my name, email, and website in this browser for the next time I comment.' ) . '</label></p>', ), ); comment_form( $comment_form );
Notes
- See: 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
Changelog
| Since 2.7.0 | Introduced. |