循环

循环(Loop)是WordPress用来通过主题的模板文件输出文章的默认机制。检索多少个文章是由阅读设置中定义的每页要显示的文章数量决定的。在循环中,WordPress会检索每个要显示在当前页面上的文章,并根据你的主题指示来格式化它。

循环从WordPress数据库中提取每个文章的数据,并在每个模板标签的位置插入适当的信息。循环中的任何HTML或PHP代码都将针对每个文章进行处理。

简单地说,“循环”名副其实的:它将逐一循环当前页面检索到的每个文章,并执行主题中指定的操作。

你可以将循环用于许多不同的事情,例如:

  • 在你的博客主页上显示文章标题和摘录;
  • 显示单个文章的内容和评论;
  • 使用模板标签在一个单独的页面上显示内容;
  • 显示自定义文章类型和自定义字段的数据。

你可以在你的模板文件中自定义循环,以显示和操作不同的内容。

详细介绍“循环”

最基本的循环:

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // Display post content
    endwhile; 
endif; 
?>

这个循环的意思是,当有文章的时候,循环显示这些文章。分解成更多的细节:

  • have_posts()函数检查是否有任意文章
  • 如果有文章,只要括号里的条件在逻辑上为true,那么while循环就会继续执行。只要have_posts()继续为true,循环就会继续

 

使用循环

循环应该放在index.php中,以及任何其他用于显示文章信息的模板中。因为你不希望一次又一次地重复你的标题,循环应该总是放在调用get_header()之后。比如说:

<?php 
get_header();
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // Display post content
    endwhile; 
endif; 
?>

在上面的例子中,循环的结束是用endwhile和endif来表示的。如上所述,循环必须总是以相同的if和while语句开始,并且必须以相同的end语句结束。

你希望应用于所有文章的任意模板标签必须放在开始和结束语句之间。

你可以包括一个自定义的404 "未找到"信息,如果没有符合指定标准的文章,就会显示出来。该信息必须放在endwhile和endif语句之间,如下面的例子所示。

一个极其简单的index.php文件看起来像:

<?php
get_header();

if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_content();
    endwhile;
else :
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' );
endif;

get_sidebar();
get_footer();
?>

 

循环能显示什么

循环可以为每个文章显示许多不同的元素。例如,许多主题中使用的一些常见模板标签有:

  • next_post_link() – 按时间顺序在当前文章之后发表的文章的链接
  • previous_post_link() – 按时间顺序在当前文章之前发表的文章的链接
  • the_category() – 与正在浏览的文章或页面关联的类别
  • the_author() – 文章或网页的作者
  • the_content() – 文章或网页的内容
  • the_excerpt() – 一篇文章内容的前55个单词,后跟一个省略号(…)或指向全文的阅读更多链接。您还可以使用文章的“摘录”字段自定义特定摘录的长度。
  • the_ID() – 文章或网页的ID
  • the_meta() – 文章或页面关联的自定义字段
  • the_shortlink() – 使用网站url和文章或页面ID构成的短链接
  • the_tags() – 文章关联的标签
  • the_title() – 文章或网页的标题
  • the_time() – 文章或网页的日期或时间,可以使用标准的php日期函数格式化来定制

你也可以使用条件标签,如:

  • is_home() – 如果当前页面是主页,则返回true
  • is_admin() – 如果在管理屏幕内,返回true,否则返回false
  • is_single() – 如果页面当前显示的是单一的文章,则返回true
  • is_page() – 如果页面当前显示的是单页,则返回true
  • is_page_template() – 可以用来确定一个页面是否使用了特定的模板,例如:is_page_template('about-page.php')
  • is_category() – 如果页面或文章有指定的类别,则返回true,例如:is_category('news')
  • is_tag() – 如果页面或文章有指定的标签,则返回true
  • is_author() – 如果在作者的存档页内,则返回true
  • is_search() – 如果当前页面是搜索结果页面,则返回true
  • is_404() – 如果当前页不存在,则返回true
  • has_excerpt() – 如果文章或页面有摘录,则返回true

 

示例

让我们看一看在动作中的循环的一些示例:

 

基本示例

 

博客存档

大多数博客都有一个博客存档页面,可以显示许多内容,包括文章标题、缩略图和摘录。下面的示例显示了一个简单的循环,用于检查是否有任意文章,如果有,则输出每个文章的标题、缩略图和摘录。如果不存在文章,则会显示括号中的提示信息。

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        the_title( '<h2>', '</h2>' ); 
        the_post_thumbnail(); 
        the_excerpt();
    endwhile; 
else: 
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); 
endif; 
?>

 

单个文章

在WordPress中,每个文章都有自己的页面,显示该文章的相关信息。模板标签允许你定制你想显示的信息。

在下面的例子中,循环输出文章的标题和内容。你可以在一个文章或页面模板文件中使用这个例子来显示文章的最基本信息。你也可以定制这个模板,为文章添加更多的数据,比如说类别。

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        the_title( '<h1>', '</h1>' ); 
        the_content();
    endwhile; 
else: 
    _e( 'Sorry, no pages matched your criteria.', 'textdomain' ); 
endif; 
?>

 

中级示例

 

不同类别的文章应用不同风格

下面的例子做了几件事:

  • 首先,它显示每个文章的标题、时间、作者、内容和类别,与上面的单个文章例子类似
  • 接下来,它使类别ID为 "3"的文章有可能被赋予不同的风格,利用in_category()模板标签。

本例中的代码注释提供了整个循环的每个阶段的细节

<?php
// Start the Loop.
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        /* * See if the current post is in category 3.
          * If it is, the div is given the CSS class "post-category-three".
          * Otherwise, the div is given the CSS class "post".
        */
        if ( in_category( 3 ) ) : ?>
        <div class="post-category-three">
        <?php else : ?>
        <div class="post">
        <?php endif; 

            // Display the post's title.
            the_title( '<h2>', ';</h2>' ); 

            // Display a link to other posts by this posts author.
            printf( __( 'Posted by %s', 'textdomain' ), get_the_author_posts_link() );

            // Display the post's content in a div.
            ?>
            <div class="entry">
                <?php the_content() ?>
             </div>
    
            <?php
            // Display a comma separated list of the post's categories.
            _e( 'Posted in ', 'textdomain' ); the_category( ', ' ); 

        // closes the first div box with the class of "post" or "post-cat-three"
       ?>
       </div>

    <?php 
    // Stop the Loop, but allow for a "if not posts" situation
    endwhile; 

else :
    /*
      * The very first "if" tested to see if there were any posts to
      * display. This "else" part tells what do if there weren't any.
     */
     _e( 'Sorry, no posts matched your criteria.', 'textdomain' );
 
// Completely stop the Loop.
 endif;
?>

 

多重循环

在某些情况下,你可能需要使用一个以上的循环。例如,你可能想在页面顶部的内容列表中显示文章的标题,然后在页面的更下方显示内容。由于查询没有被改变,当我们需要第二次循环浏览文章时,我们只需要倒回循环。为此,我们将使用函数rewind_posts()

 

rewind_posts的使用

你可以使用rewind_posts()对同一个查询进行第二次循环。如果你想在一个页面的不同位置显示两次相同的查询,这很有用。

下面是一个使用rewind_posts()的例子:

<?php
// Start the main loop
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_title();
    endwhile;
endif;

// Use rewind_posts() to use the query a second time.
rewind_posts();

// Start a new loop
while ( have_posts() ) : the_post();
    the_content();
endwhile;
?>

 

创建二级查询和循环

使用同一查询的两个循环是相对容易的,但并不总是你所需要的。相反,你经常想创建一个二级查询,在模板上显示不同的内容。例如,你可能想在同一个页面上显示两组文章,但对每组做不同的事情。一个常见的例子,如下所示,显示一个单一的文章,在单一的文章下面有一个同一类别的文章列表。

<?php
// The main query.
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_title();
        the_content();
    endwhile;
else :
    // When no posts are found, output this text.
    _e( 'Sorry, no posts matched your criteria.' );
endif;
wp_reset_postdata();                                                        

/*
 * The secondary query. Note that you can use any category name here. In our example,
 * we use "example-category".
 */
$secondary_query = new WP_Query( 'category_name=example-category' );        

// The second loop. 
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来查询一个特定的类别;在我们的例子中,选择了example-category slug。

请注意,上面的例子中的常规循环有一个区别:它调用wp_reset_postdata()来重置文章数据。在你使用第二个循环之前,你需要重置文章数据。有两种方法可以做到这一点。

  1. 通过使用rewind_posts()函数;
  2. 通过创建新查询对象

 

重置多个循环

当在一个模板中使用多个循环时,重要的是你要重置它们。由于数据在全局$post变量中的存储和使用方式,不这样做会导致意外的结果。有三种主要方式来重置循环,这取决于它们的调用方式。

 

wp_reset_postdata的使用

当您使用WP_Query运行自定义或多个循环时,请使用wp_reset_postdata()。这个函数将全局$post变量恢复到主查询中的当前文章。如果您遵循最佳实践,这是您最常用的重置循环的函数。

要正确使用这个函数,请将以下代码放在任何带有WP_Query的循环之后:

<?php wp_reset_postdata(); ?>

下面是一个使用WP_Query的循环的例子,它被wp_reset_postdata()重置。

 <?php 
// Example argument that defines three posts per page. 
$args = array( 'posts_per_page' => 3 ); 

// Variable to call WP_Query. 
$the_query = new WP_Query( $args ); 

if ( $the_query->have_posts() ) : 
    // Start the Loop 
    while ( $the_query->have_posts() ) : $the_query->the_post(); 
        the_title(); 
        the_excerpt(); 
    // End the Loop 
    endwhile; 
else: 
// If no posts match this query, output this text. 
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); 
endif; 

wp_reset_postdata(); 
?> 

 

wp_reset_query的使用

使用wp_reset_query()可以将WP_Query和全局$post数据恢复到原来的主查询。如果您在您的循环中使用query_posts(),您必须使用这个函数来重置您的循环。你可以在使用WP_Query的自定义循环后使用它,因为它实际上在运行时调用wp_reset_postdata()。不过,最好的做法是在任何涉及WP_Query的自定义循环中使用wp_reset_postdata()

query_posts()不是最佳做法,如果可能的话,应该避免使用。因此,你不应该对wp_reset_query()有太多使用。

要正确使用这个函数,请将以下代码放在任何带有query_posts()的循环之后。

<?php wp_reset_query(); ?>