wp_list_comments()
云策文档标注
概述
wp_list_comments() 是 WordPress 核心函数,用于在 comments.php 模板中显示评论列表。它支持多种参数自定义输出格式,如列表样式、分页、评论深度等,并可结合 Walker_Comment 类或自定义回调函数进行高级控制。
关键要点
- 主要用于在模板中输出评论列表,通常与 get_comments() 或 WP_Query 配合使用。
- 接受 $args 数组参数,包括 style(列表样式)、callback(自定义回调)、max_depth(评论深度)、type(评论类型)等。
- 默认使用 Walker_Comment 类处理评论遍历,支持嵌套评论和分页。
- 可通过 wp_list_comments_args 过滤器修改参数。
- 返回类型取决于 echo 参数:若为 true 则直接输出,否则返回 HTML 字符串。
代码示例
// 基本用法,显示所有评论
wp_list_comments();
// 自定义参数示例
wp_list_comments(array(
'style' => 'ol',
'callback' => 'mytheme_comment',
'max_depth' => 5,
'avatar_size' => 60,
'type' => 'comment',
'reverse_top_level' => false
));注意事项
- 需在 comments.php 模板文件中调用,确保评论数据已加载。
- 使用 'div' 样式时可能存在额外标记的 bug,需注意 CSS 调整。
- 分页和评论深度设置可受后台“讨论设置”影响,但主题可覆盖。
- 自定义回调函数需在 functions.php 中定义,并处理评论 HTML 结构。
原文内容
Displays a list of comments.
Description
Used in the comments.php template to list comments for a particular post.
See also
- WP_Query::$comments
Parameters
$argsstring|arrayoptional-
Formatting options.
walkerobjectInstance of a Walker class to list comments. Default null.max_depthintThe maximum comments depth.stylestringThe style of list ordering. Accepts'ul','ol', or'div'.
'div'will result in no additional list markup. Default'ul'.callbackcallableCallback function to use. Default null.end-callbackcallableCallback function to use at the end. Default null.typestringType of comments to list. Accepts'all','comment','pingback','trackback','pings'. Default'all'.pageintPage ID to list comments for.per_pageintNumber of comments to list per page.avatar_sizeintHeight and width dimensions of the avatar size. Default 32.reverse_top_levelboolOrdering of the listed comments. If true, will display newest comments first. Default null.reverse_childrenboolWhether to reverse child comments in the list. Default null.formatstringHow to format the comments list. Accepts'html5','xhtml'.
Default'html5'if the theme supports it.short_pingboolWhether to output short pings. Default false.echoboolWhether to echo the output or return it. Default true.
Default:
array() $commentsWP_Comment[]optional-
Array of WP_Comment objects.
Default:
null
Source
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 = (int) 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 = (int) get_query_var( 'comments_per_page' );
if ( (int) $parsed_args['page'] !== $current_cpage || (int) $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 = (int) get_query_var( 'cpage' );
if ( 'newest' === $default_comments_page ) {
$parsed_args['cpage'] = $cpage;
} elseif ( 1 === $cpage ) {
/*
* When the first page shows the oldest comments,
* post permalink is the same as the comment permalink.
*/
$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 !== (int) $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'];
$parsed_args['per_page'] = (int) $parsed_args['per_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' ) );
}
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;
}
}
Hooks
- apply_filters( ‘wp_list_comments_args’, array $parsed_args )
-
Filters the arguments used in retrieving the comment list.
Changelog
| Version | Description |
|---|---|
| 2.7.0 | Introduced. |
Skip to note 8 content
Steven Lin
Example migrated from Codex:
Comments Only With A Custom Comment Display
Displays just comments (no pingbacks or trackbacks) while using a custom callback function to control the look of the comment. You may want to add a
max_depth=Xparameter, if the reply links are not appearing.<ul class="commentlist"> </ul>You will need to define your custom callback function in your theme’s functions.php file. Here is an example:
function mytheme_comment($comment, $args, $depth) { if ( 'div' === $args['style'] ) { $tag = 'div'; $add_below = 'comment'; } else { $tag = 'li'; $add_below = 'div-comment'; }?> < id="comment-"> <div id="div-comment-<?php comment_ID() ?>" class="comment-body"> <div class="comment-author vcard">%s</cite> <span class="says">says:</span>' ), get_comment_author_link() ); ?> </div>comment_approved == '0' ) { ?> <em class="comment-awaiting-moderation"></em><br/> <div class="comment-meta commentmetadata"> <a href="<?php echo htmlspecialchars( get_comment_link( $comment->comment_ID ) ); ?>"> </a> </div> <div class="reply"> $add_below, 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?> </div> </div></pre> <p>Note the lack of a trailing <code></li></code>. In order to accommodate nested replies, WordPress will add the appropriate closing tag after listing any child elements.</p> </div><!-- .comment-content --> <section id='feedback-3912' class='wporg-has-embedded-code feedback hide-if-js' data-comment-count='0'> </section><!-- .feedback --> <footer class='feedback-links wporg-dot-link-list' > <a role="button" class="feedback-login" href="https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_list_comments%2F%3Freplytocom%3D3912%23feedback-editor-3912" rel="nofollow">Log in to add feedback</a></footer> </article><!-- .comment-body --> </li> <li id="comment-2927" data-comment-id="2927" class="comment byuser comment-author-truser odd alt thread-even depth-1"> <article id="div-comment-2927" class="comment-body"> <a href="#comment-content-2927" class="screen-reader-text">Skip to note 9 content</a> <header class="comment-meta"> <div class="comment-author vcard"> <span class="comment-author-attribution"> <a href="https://profiles.wordpress.org/truser/" rel="external nofollow" class="url">Mustafa KUCUK</a> </span> <a class="comment-date" href="https://developer.wordpress.org/reference/functions/wp_list_comments/#comment-2927"> <time datetime="2018-10-26T12:24:33+00:00"> 7 years ago </time> </a> </div> <div class="user-note-voting" data-nonce="a378ece171" data-can-vote="false"><a class="user-note-voting-up" title="You must log in to vote on the helpfulness of this note" data-id="2927" data-vote="up" href="https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_list_comments%2F%23comment-2927"><span class="screen-reader-text">You must log in to vote on the helpfulness of this note</span></a><span class="user-note-voting-count " title="100% like this"><span class="screen-reader-text">Vote results for this note: </span>2</span><a class="user-note-voting-down" title="You must log in to vote on the helpfulness of this note" data-id="2927" data-vote="down" href="https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fwp_list_comments%2F%23comment-2927"><span class="screen-reader-text">You must log in to vote on the helpfulness of this note</span></a></div> </header> <!-- .comment-metadata --> <div class="wporg-has-embedded-code comment-content" id="comment-content-2927"> <p>If you are using WordPress 4.9.6 or higher and not showing “Comment is awaiting moderation” alert.</p> <p>You can follow the steps below.</p> <p>– ) Settings -> Discussion -> enable “Show comments cookies opt-in checkbox.”<br /> – ) 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.”</p> <p>That’s it.</p> <p>If you want to customize this checkbox field, you can use this code.</p> <pre class="wp-block-code"><code lang="php" class="language-php line-numbers">$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 );Skip to note 10 content
Anonymous User
wp_list_comments()will not do anything by itself. It has to be called from inside thecomments templatefile.An example:
The page/post file where you want to insert comments:
Then, in
comments.php:<div> </div>Skip to note 11 content
Steven Lin
Example migrated from Codex:
Outputs an ordered list of comments for a specific page or post. Things like threading or paging being enabled or disabled are controlled via the Settings Discussion SubPanel.
<ol class="commentlist"> XXX, 'status' => 'approve' //Change this to the type of comments to be displayed )); //Display the list of comments wp_list_comments(array( 'per_page' => 10, //Allow comment pagination 'reverse_top_level' => false //Show the oldest comments at the top of the list ), $comments); ?> </ol>Skip to note 12 content
Mehadi Hasan Juber
Customize the default wp_list_comments() ;
<ol class="comment-list"> 60, 'max_depth' => 5, 'style' => 'ol', 'short_ping' => true, 'type' => 'comment', ) ); ?> </ol><!-- .comment-list -->Skip to note 13 content
Steven Lin
Example migrated from Codex:
Default Usage
Outputs an ordered list of the comments. Things like threading or paging being enabled or disabled are controlled via the Settings Discussion SubPanel.
<ol class="commentlist"> </ol>Skip to note 14 content
Mehedi Foysal
$cpage = get_query_var( 'cpage' ) ? get_query_var( 'cpage' ) : 1; wp_list_comments( array( '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, ) );