循环是 WordPress 通过主题模板文件输出文章的默认机制 。在循环中,WordPress 遍历当前页面获取到的所有文章,然后使用主题中的模板标签将其格式化并输出。
循环从WordPress数据库中提取每个文章的数据,并在每个模板标签的位置插入适当的信息。循环中的所有HTML或PHP代码都将针对每个文章进行处理。
简而言之,循环的名称是真实的:它一次遍历当前页面检索到的每个文章,并执行主题中指定的操作。
您可以用 WordPress 循环来做很多事情,例如:
- 在网站首页显示多个文章模块
- 在文章详情页面显示内容和评论
- 在侧边栏中显示最新文章或热门文章
- 显示指定文章类型或分类方法中的数据
- 根据指定的条件获取数据并显示在文章模块中
您可以自定义模板文件中的“循环”以显示和操作不同的内容。
循环细节
循环的基本使用方法如下。
<?php
if ( have_posts() ) :
while ( have_posts() ) : the_post();
// 显示文章内容
endwhile;
endif;
?>
上面的代码首先判断是否有循环,如果有,则逐个显示循环中的内容。
- have_posts() 函数检查当前页面是否有文章。
- 只要括号中的条件逻辑为真,
while
循环就会继一直执行下去。
使用循环
循环应放在 index.php
或其他用来显示文章的模板中。因为我们不想在每个文章中都显示网站页头,所以循环代码应该放在 get_header()
之后。
<?php
get_header();
//循环从这里开始
if ( have_posts() ) :
while ( have_posts() ) : the_post();
// 显示文章内容
endwhile;
endif;
?>
如以上代码所示,循环必须以 if
和 while
语句开头,以 endwhile
和 endif
语句结束。用以显示文章内容的模板标签必须在循环开始语句和结束语句中间。
一个非常简单的index.php
文件如下所示:
<?php
get_header();
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_content();
endwhile;
else :
_e( '抱歉,未找到您需要的文章。', 'textdomain' );
endif;
get_sidebar();
get_footer();
?>
可以在循环中显示什么
您可以在循环中使用模板标签显示各种文章内容、文章自定义字段,下面是一些常用的模板标签:
next_post_link()
:显示在当前文章之后 发布的文章的链接previous_post_link()
– 显示在当前文章之前发布的文章的链接the_category()
:显示当前文章所在的分类the_author()
:显示文章作者the_content()
:显示文章正文内容the_excerpt()
:显示文章摘要the_ID()
:显示文章或页面 IDthe_meta()
:显示文章或页面的自定义字段the_shortlink()
:显示文章的短链接the_tags()
:显示文章所包含的标签the_title()
:显示文章标题the_time()
:显示文章发布时间
显示文章的时候,我们可以使用条件标签控制文章是否在满足某种条件的情况下显示。例如:
is_home()
–如果当前页面是主页,则返回trueis_admin()
–如果在管理后台返回true,否则返回falseis_single()
–如果页面当前仅显示单个文章,则返回trueis_page()
–如果页面当前仅显示单个页面,则返回trueis_page_template()
–可用于确定页面是否使用特定模板,例如:is_page_template('about-page.php')
is_category()
–如果页面或文章具有指定的类别,则返回true,例如:is_category('news')
is_tag()
–如果页面或文章具有指定的标签,则返回trueis_author()
–如果在作者的存档页面内,则返回trueis_search()
–如果当前页面是搜索结果页面,则返回trueis_404()
–如果当前页面不存在,则返回truehas_excerpt()
–如果文章或页面有摘要,则返回true
示例
下面让我们看一些 WordPress 循环的真实使用示例。
基本示例
文章列表页
大多数网站都有文章列表页面,在列表页面中,可以显示这个列表中所有文章的标题、缩略图、摘要、分类等信息。下面的示例是一个简单的列表页面,示例代码首先检查是否有文章,如果有,显示文章标题、缩略图、摘要,如果没有,则显示提示消息。
<?php
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title( '<h2>', '</h2>' );
the_post_thumbnail();
the_excerpt();
endwhile;
else:
_e( '抱歉,未找到您需要的文章。', 'textdomain' );
endif;
?>
文章详情页
在 WordPress 中,每个文章都有自己的详情页面,您可以使用模板标签在这个页面上显示文章的各种信息。
在下面的示例中,模板循环显示了文章的标题和内容,除此之外,您还可以显示文章正文、文章作者、发表时间等信息。
<?php
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title( '<h1>', '</h1>' );
the_content();
endwhile;
else:
_e( '抱歉,未找到您需要的文章。', 'textdomain' );
endif;
?>
中级示例
不同分类显示不同文章样式
我们来看一下模板示例,在这个示例中:
- 首先,显示每篇文章的标题、发布时间、作者、正文和分类。
- 然后,我们利用判断函数 in_category() 来为分类 ID 为 3 的文章显示不同的样式。
<?php
// 开始循环
if ( have_posts() ) :
while ( have_posts() ) : the_post();
// 判断文章是否在分类 3 中,如果是,添加 CSS 类 "post-category-three". 否则,添加 CSS 类 "post".
if ( in_category( 3 ) ) : ?>
<div class="post-category-three">
<?php else : ?>
<div class="post">
<?php endif;
// 显示文章标题
the_title( '<h2>', ';</h2>' );
// 显示该文章作者存档的链接
printf( __( '作者 %s', 'textdomain' ), get_the_author_posts_link() );
// 显示文章内容
?>
<div class="entry">
<?php the_content() ?>
</div>
<?php
// 显示逗号分隔的文章分类
_e( '文章分类 ', 'textdomain' ); the_category( ', ' );
// 关闭 div
?>
</div>
<?php
// 结束循环,下面是没有文章时显示的内容
endwhile;
else :
// 如果没有文章,显示提示消息
_e( '抱歉,未找到您需要的文章。', 'textdomain' );
// 结束判断和循环
endif;
?>
主循环
主循环是 WordPress 中的一个非常重要的概念,在开始学习多个循环之前,您首先需要了解一下什么是主循环。
当访问 WordPress 站点的时候,WordPress 会根据您访问的页面新建一个文章查询和循环,设置一个 $wp_query
全局变量。这个变量就是主循环数据的变量,您可以直接在页面模板中循环这个数据来输出文章。
看一下下面的代码:
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title();
endwhile;
endif;
为了说明主循环,我们稍微改写一下代码。
if ( $wp_query->have_posts() ) :
while ( $wp_query->have_posts() ) : $wp_query->the_post();
the_title();
endwhile;
endif;
两段代码是等效的,为了保持代码的简洁性,WordPress 隐藏了全局的主循环变量 $wp_query
。
多个循环
在某些情况下,您可能需要使用多个循环。例如,您可能需要在页面顶部的内容列表中显示文章标题,然后在页面下方显示文章内容。因为使用的是同一个循环,您只需要在开始第二次循环之前重置循环即可,使用函数 rewind_posts() 即可实现这个功能。
使用 rewind_posts() 重新开始循环
您可以使用 rewind_post()
函数让循环从循环中的第一个元素重新开始,当您需要在一个页面中循环同一个查询时,这个函数非常有用。
这下面是一个rewind_posts()
示例 :
<?php
// 开始主循环
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title();
endwhile;
endif;
// 使用 rewind_posts()再次使用这个循环
rewind_posts();
// 开始新循环
while ( have_posts() ) : the_post();
the_content();
endwhile;
?>
新建查询和循环
对同一个查询使用两个循环相对容易,但并不总是您所需要的。有时候您需要在一个页面上显示不同的文章,例如,您需要在页面的左侧显示所有文章,右侧显示分类「example-category」中的文章。这种情况下,您需要新建一个文章查询,然后循环这个新的文章查询结果,示例代码如下:
<?php
// 显示所有文章
if ( have_posts() ) :
while ( have_posts() ) : the_post();
the_title();
the_content();
endwhile;
else :
_e( '抱歉,未找到您需要的文章。' );
endif;
wp_reset_postdata();
// 创建一个新的文章查询,获取分类 「category_name」中的文章。
$secondary_query = new WP_Query( 'category_name=example-category' );
// 循环新的查询结果
if ( $secondary_query->have_posts() )
echo '<ul>';
while ( $secondary_query->have_posts() ) : $secondary_query->the_post();
the_title( '<li>', '</li>' );
endwhile;
echo '</ul>';
endif;
wp_reset_postdata();
?>
如上例所示,我们首先显示主循环中的结果。然后,使用 WP_Query 类查询指定分类中的文章。
请注意,上面示例中的第二个循环和主循环还有一个区别:后者调用了
wp_reset_postdata()
函数来重置文章数据。
重置多个循环
在循环中,文章数据是存储在 $post
全局变量中的,在循环结束时,我们需要重置这个全局变量,否则会导致一些难以调试的 Bug 。根据循环调用的方式,有三个函数可以用来重置循环。
使用 wp_reset_postdata() 重置文章数据
使用 WP_Query
新建自定义循环或使用了多个循环时,请使用 wp_reset_postdata()
来重置文章数据,这个函数将全局变量 $post
变量还原到主查询中的当前文章。如果您在进行 WordPress 开发时遵循了最佳实践,该函数是用来重置循环的最常见函数。
要正确使用此功能,请在以下任何 WP_Query 循环之后放置以下代码:
<?php wp_reset_postdata(); ?>
下面是使用 WP-Query
类新建了查询和循环后,使用 wp_reset_postdata()
还原文章数据的示例代码。
<?php
// 示例参数,定义每页显示3篇文章
$args = array( 'posts_per_page' => 3 );
// 调用 WP_Query 新建文章查询
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
// 开始循环
while ( $the_query->have_posts() ) : $the_query->the_post();
the_title();
the_excerpt();
// 结束循环
endwhile;
else:
// 如果没有满足条件的文章,就返回以下文字
_e( '抱歉,未找到您需要的文章。', 'textdomain' );
endif;
wp_reset_postdata();
?>
使用 wp_reset_query() 重置主循环和文章数据
因为 query_posts()
函数新建的循环是一个主循环,在使用了这个函数新建查询后,您必须使用 wp_reset_query()
来还原查询和文章数据。如果使用了WP_Query
新建查询,您可以使用 wp_reset_query()
函数来还原文章数据(因为该函数已经调用了 wp_reset_postdata()
函数),但是最好的做法是使用 wp_reset_postadata
函数来还原使用 WP_Query
新建的自定义循环。
要正确使用此功能,请在 query_posts() 循环后放置以下代码:
<?php wp_reset_query(); ?>
因为
query_posts()
会新建一个主循环来替代当前页面的主循环,使用这个函数会带来一些副作用,新建循环时,应该尽量使用WP_Query
而不是query_posts()
函数。