大家好!我是你们今天的WordPress源码探险向导,很高兴能和大家一起深入comments_template()
这个既熟悉又有点神秘的函数。咱们今天的目标是,把它扒个精光,看看它到底是怎么找到评论模板,又怎么把它们加载出来的。准备好,我们要开始了!
一、初识comments_template()
:一个简单的开始
首先,我们先来回顾一下comments_template()
最常见的用法。通常,我们会在WordPress主题的single.php
或者page.php
这样的模板文件中看到类似这样的代码:
<?php
if ( comments_open() || get_comments_number() ) {
comments_template();
}
?>
这段代码的意思很简单:如果当前文章允许评论,或者已经有评论了,那就加载评论模板。comments_template()
就是负责找到并加载这个评论模板的关键。
二、comments_template()
源码剖析:抽丝剥茧
接下来,让我们打开WordPress的源码(通常在/wp-includes/comment-template.php
),一起看看comments_template()
的真面目。为了方便大家理解,我们把源码简化一下,去掉一些不常用的参数和判断,保留核心逻辑。
function comments_template( $template = '', $separate_comments = false ) {
global $wp_query, $withcomments, $post, $wpdb, $id, $comment, $user_login, $user_ID, $overridden_cpage;
if ( ! ( is_singular() && ( have_comments() || 'open' == $post->comment_status ) ) ) {
return;
}
$req = get_option( 'require_name_email' );
if ( in_array( $wp_query->query_vars['pagename'], array('feed', 'rdf', 'rss', 'rss2', 'atom') ) ) {
return;
}
$template = apply_filters( 'comments_template', $template );
if ( empty( $template ) ) {
$template = locate_template( array( 'comments.php', 'wp-comments.php' ), true, false );
return;
}
load_template( $template, true );
}
让我们一步一步解读这段代码:
-
条件判断:守门员
if ( ! ( is_singular() && ( have_comments() || 'open' == $post->comment_status ) ) ) { return; }
这部分代码是
comments_template()
的守门员。它会检查当前页面是否是文章或页面(is_singular()
),以及该文章/页面是否允许评论('open' == $post->comment_status
)或者已经有评论(have_comments()
)。如果不满足这些条件,函数会直接返回,什么也不做。这意味着,在非文章/页面或者评论关闭的情况下,comments_template()
不会加载任何模板。 -
Feed检测:特殊情况处理
if ( in_array( $wp_query->query_vars['pagename'], array('feed', 'rdf', 'rss', 'rss2', 'atom') ) ) { return; }
这部分代码检测当前页面是否是feed页面。如果是feed页面,则直接返回,不加载评论模板。因为feed页面通常不需要显示评论。
-
comments_template
过滤器:预处理$template = apply_filters( 'comments_template', $template );
这是一个WordPress的钩子(hook)。它允许其他插件或主题通过
add_filter()
函数来修改$template
变量的值。也就是说,在真正加载模板之前,你可以通过这个钩子来指定要加载的评论模板文件。这为定制评论模板提供了极大的灵活性。 -
locate_template()
:寻找宝藏if ( empty( $template ) ) { $template = locate_template( array( 'comments.php', 'wp-comments.php' ), true, false ); return; }
这部分代码是
comments_template()
的核心逻辑。如果$template
变量为空(也就是没有通过comments_template
过滤器指定模板),那么locate_template()
函数就会被调用。locate_template()
函数负责在主题目录中查找评论模板文件。-
locate_template( array( 'comments.php', 'wp-comments.php' ), true, false )
array( 'comments.php', 'wp-comments.php' )
: 这是一个模板文件名的数组。locate_template()
会按照数组中的顺序依次查找这些文件。也就是说,它会先查找comments.php
,如果找不到,再查找wp-comments.php
。true
: 这个参数表示如果找到了模板文件,就立即加载它。false
: 这个参数表示不要加载父主题中的模板文件。
-
-
load_template()
:加载模板load_template( $template, true );
如果
locate_template()
找到了评论模板文件,或者通过comments_template
过滤器指定了模板文件,那么load_template()
函数就会被调用来加载这个模板文件。-
load_template( $template, true )
$template
: 这是要加载的模板文件的路径。true
: 这个参数表示在加载模板文件之前,不要加载WordPress的模板标签。
-
三、locate_template()
的寻宝之旅:深入挖掘
locate_template()
函数是寻找评论模板的关键。让我们更深入地了解它。
function locate_template( $template_names, $load = false, $require_once = true ) {
$located = false;
foreach ( (array) $template_names as $template_name ) {
if ( ! $template_name )
continue;
if ( file_exists( STYLESHEETPATH . '/' . $template_name) ) {
$located = STYLESHEETPATH . '/' . $template_name;
break;
} elseif ( file_exists( TEMPLATEPATH . '/' . $template_name ) ) {
$located = TEMPLATEPATH . '/' . $template_name;
break;
} elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) {
$located = ABSPATH . WPINC . '/theme-compat/' . $template_name;
break;
}
}
if ( ( true == $load ) && ( '' != $located ) )
load_template( $located, $require_once );
return $located;
}
这个函数的工作方式如下:
-
循环查找:遍历模板文件名数组
foreach ( (array) $template_names as $template_name ) { if ( ! $template_name ) continue;
locate_template()
会遍历$template_names
数组中的每一个模板文件名。如果文件名为空,则跳过。 -
优先级查找:子主题 > 父主题 > 默认模板
if ( file_exists( STYLESHEETPATH . '/' . $template_name) ) { $located = STYLESHEETPATH . '/' . $template_name; break; } elseif ( file_exists( TEMPLATEPATH . '/' . $template_name ) ) { $located = TEMPLATEPATH . '/' . $template_name; break; } elseif ( file_exists( ABSPATH . WPINC . '/theme-compat/' . $template_name ) ) { $located = ABSPATH . WPINC . '/theme-compat/' . $template_name; break; }
locate_template()
会按照以下顺序查找模板文件:- 子主题目录(
STYLESHEETPATH
): 如果当前使用的是子主题,locate_template()
会首先在子主题目录中查找模板文件。 - 父主题目录(
TEMPLATEPATH
): 如果在子主题目录中没有找到模板文件,locate_template()
会在父主题目录中查找。 - WordPress默认模板目录(
ABSPATH . WPINC . '/theme-compat/'
): 如果父主题目录中也没有找到模板文件,locate_template()
会在WordPress的默认模板目录中查找。这个目录包含一些默认的模板文件,用于保证WordPress在缺少主题的情况下也能正常运行。
一旦找到模板文件,
$located
变量就会被设置为该文件的路径,并且循环会立即结束(break
)。 - 子主题目录(
-
加载模板(可选):根据
$load
参数决定if ( ( true == $load ) && ( '' != $located ) ) load_template( $located, $require_once );
如果
$load
参数为true
,并且$located
变量不为空(也就是找到了模板文件),那么load_template()
函数就会被调用来加载该模板文件。$require_once
参数决定是否使用require_once
来加载模板文件。 -
返回模板路径:方便后续处理
return $located;
locate_template()
函数会返回找到的模板文件的路径。如果没有找到模板文件,则返回false
。
四、主题文件结构:评论模板的安身之所
现在我们知道了comments_template()
和locate_template()
是如何工作的,接下来让我们看看评论模板文件通常放在主题的什么位置。
一般来说,评论模板文件(comments.php
或wp-comments.php
)应该放在主题的根目录下。如果使用了子主题,那么最好将评论模板文件放在子主题的根目录下,这样可以覆盖父主题的评论模板。
以下是一个典型的WordPress主题文件结构:
my-theme/
├── style.css
├── index.php
├── single.php
├── page.php
├── comments.php <-- 评论模板文件
├── footer.php
├── header.php
└── ...
五、实战演练:定制评论模板
现在,让我们来做一个实际的例子,演示如何定制评论模板。
-
创建
comments.php
文件: 首先,在你的主题(或者子主题)的根目录下创建一个名为comments.php
的文件。 -
编写模板代码: 在
comments.php
文件中,你可以编写自定义的评论模板代码。例如,你可以修改评论的显示方式,添加自定义的评论表单,或者修改评论的排序方式。<?php /** * The template for displaying comments * * This is the template that displays the area of the page that contains both the current comments * and the comment form. * * @link https://developer.wordpress.org/themes/basics/template-hierarchy/ * * @package WordPress * @subpackage Twenty_Nineteen * @since 1.0.0 */ /* * If the current post is protected by a password and * the visitor has not yet entered the password we will * return early without loading the comments. */ if ( post_password_required() ) { return; } ?> <div id="comments" class="comments-area"> <?php // You can start editing here -- including this comment! if ( have_comments() ) : ?> <h2 class="comments-title"> <?php $comments_number = get_comments_number(); if ( '1' === $comments_number ) { /* translators: %s: Post title. */ printf( _x( 'One thought on “%s”', 'comments title', 'twentynineteen' ), get_the_title() ); } else { printf( /* translators: 1: Number of comments, 2: Post title. */ _nx( '%1$s thought on “%2$s”', '%1$s thoughts on “%2$s”', $comments_number, 'comments title', 'twentynineteen' ), number_format_i18n( $comments_number ), get_the_title() ); } ?> </h2><!-- .comments-title --> <?php the_comments_navigation(); ?> <ol class="comment-list"> <?php wp_list_comments( array( 'style' => 'ol', 'short_ping' => true, 'avatar_size' => 42, ) ); ?> </ol><!-- .comment-list --> <?php the_comments_navigation(); // If comments are closed and there are comments, let's leave a little note, shall we? if ( ! comments_open() ) : ?> <p class="no-comments"><?php _e( 'Comments are closed.', 'twentynineteen' ); ?></p> <?php endif; endif; // Check for have_comments(). comment_form(); ?> </div><!-- #comments -->
-
修改
single.php
或page.php
: 在你的single.php
或page.php
文件中,确保调用了comments_template()
函数。<?php if ( comments_open() || get_comments_number() ) { comments_template(); } ?>
-
测试: 访问你的文章或页面,看看你的自定义评论模板是否生效了。
六、高级技巧:使用comments_template
过滤器
除了直接修改comments.php
文件之外,你还可以使用comments_template
过滤器来指定要加载的评论模板文件。这在某些情况下非常有用,例如,你想要根据文章的类型加载不同的评论模板。
function my_custom_comments_template( $template ) {
global $post;
if ( $post->post_type == 'movie' ) {
$template = get_stylesheet_directory() . '/comments-movie.php';
}
return $template;
}
add_filter( 'comments_template', 'my_custom_comments_template' );
这段代码的意思是:如果当前文章的类型是movie
,那么就加载comments-movie.php
作为评论模板。否则,就使用默认的评论模板。
七、常见问题与解答
问题 | 解答 |
---|---|
评论模板不生效怎么办? | 1. 确保comments.php 文件存在于你的主题或子主题的根目录下。 2. 检查single.php 或page.php 文件中是否正确调用了comments_template() 函数。 3. 清空WordPress缓存和浏览器缓存。 4. 禁用所有插件,看看是否是插件冲突导致的。 5. 检查主题的functions.php 文件,看看是否有代码阻止了评论模板的加载。 |
如何修改评论表单的样式? | 1. 直接修改comments.php 文件中的评论表单代码。 2. 使用CSS样式来修改评论表单的样式。 3. 使用comment_form_defaults 过滤器来修改评论表单的默认参数。 |
如何根据文章类型加载不同的评论模板? | 使用comments_template 过滤器。参考上面的高级技巧部分。 |
如何禁用评论? | 1. 在WordPress后台的文章编辑页面中,取消勾选“允许评论”选项。 2. 在WordPress后台的“设置” -> “讨论”页面中,取消勾选“允许所有人对新文章发表评论”选项。 3. 使用插件来禁用评论。 |
八、总结
comments_template()
函数是WordPress评论系统的核心组成部分。通过深入了解它的源码,我们可以更好地理解WordPress主题的结构,定制评论模板,以及解决评论相关的问题。希望今天的讲解对大家有所帮助。记住,代码的世界就像一个巨大的迷宫,探索的乐趣无穷无尽。下次再见!