掌握WP_Query的循环使用

141 阅读2分钟

正如我在这个系列的介绍中所述,这个 [WP_Query](https://developer.wordpress.org/reference/classes/wp_query/)类有四个主要元素。

  • 查询的参数,使用的参数将在本系列中详细介绍
  • 查询本身
  • 循环,它将输出帖子内容、标题或任何你想显示的东西
  • 结束:关闭if和while标签并重设帖子数据

在本教程中,我将向你展示如何使用WP_Query ,包括构建循环的两种主要方式以及如何使用多个循环。

循环的适用范围

如果没有循环,你的页面上将不会显示任何东西。在WordPress使用你定义的参数运行查询后,它需要被告知从它获取的数据中输出什么。这就是循环出现的地方。

所以,循环出现在你的查询之后,它使用三个标签。

  • if( $query->have_posts() ) 检查是否有任何帖子。它通过检查我们查询的post_count 属性的值是否小于current_post + 1 的值来实现。
  • while( $query->have_posts() ) 只要有帖子要检索,就对每个帖子重复这个循环。正如你所看到的,这个have_posts() 方法与我们之前调用的检查是否有任何帖子的方法相同。请记住,这个方法并不增加帖子计数器。它只是让我们知道循环中是否有任何帖子,或者我们是否处于循环的末端。一旦我们到达终点,它也会自动倒回循环。
  • $query->the_post() 访问特定的帖子。它还做其他一些事情,比如检索下一个帖子,在那里增加帖子计数器。它还设置了全局帖子数据供我们使用。

当你在循环中时,你不应该调用have_posts() 方法。这是因为have_posts() 将使循环倒退到开始,你将陷入无限循环。

现在,这就是循环在WP_Query 类中的作用。

<?php

$args = array(
    // Arguments for your query.
);

// Custom query.
$query = new WP_Query( $args );

// Check that we have query results.
if ( $query->have_posts() ) {

    // Start looping over the query results.
    while ( $query->have_posts() ) {
        $query->the_post();
        // Contents of the queried post results go here.
    }

}

// Restore original post data.
wp_reset_postdata();

?>

运行完循环后,剩下的就是用wp_reset_postdata() 来整理东西。

循环的结构

你的循环的结构方式将取决于你想从你的帖子中显示什么数据。下面是一个循环的例子,它输出文章标题、特色图片和摘录。你可以在存档页面上使用这样的循环。

<?php

$args = array(
    // Arguments for your query.
);

// Custom query.
$query = new WP_Query( $args );

// Check that we have query results.
if ( $query->have_posts() ) {

    // Start looping over the query results.
    while ( $query->have_posts() ) {

        $query->the_post();

        ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php post_thumbnail( 'thumbnail' );?>
            </a>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php the_title(); ?>
            </a>
            <?php the_excerpt(); ?>
        </article>

        <?php

    }

}

// Restore original post data.
wp_reset_postdata();

?>

这个循环显示的正是我上面描述的内容:特色图片、标题和摘录。

循环的进一步发展:检查内容

但有时你可能想在你的文章列表前添加一个标题,或者你可能想把它们都包含在一个包含元素中。如果你只是在循环之前添加这个,那么无论查询是否真的返回任何数据,它都会被输出,这意味着你可能会有一个标题,但下面什么都没有,或者一些不必要的标记。

这一点很容易解决,只要把包围的元素或标题放在你的if 标签里就可以了。

<?php

$args = array(
    // Arguments for your query.
);

// Custom query.
$query = new WP_Query( $args );

// Check that we have query results.
if ( $query->have_posts() ) {

    
    echo '<section class="clear">';
        echo '<h2>' . __( 'Heading', 'tutsplus' ) . '</h2>';
    
        // Start looping over the query results.
        while ( $query->have_posts() ) {
    
            $query->the_post();
    
            ?>
    
            <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php post_thumbnail( 'thumbnail' );?>
                </a>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
                <?php the_excerpt(); ?>
            </article>
    
            <?php
    
        }
    
    echo '</section>';

}

// Restore original post data.
wp_reset_postdata();

?>

在这里,你可以看到我已经检查了我的查询是否有任何帖子,如果有,我已经打开了一个包含元素并添加了一个标题。

如果你想把你的查询结果以列表的形式输出,这也很有用。比方说,我想创建一个给定类别中所有帖子的列表。ul 元素不在我的循环内,因为它与一个特定的帖子无关,但我只想在有帖子时输出它。所以我使用这个。

<?php

$args = array(
    'category_name' => 'category-slug',
    'post_type' => 'post'
);

// Custom query.
$query = new WP_Query( $args );

// Check that we have query results.
if ( $query->have_posts() ) {

    echo '<ul class="category posts">';

        // Start looping over the query results.
        while ( $query->have_posts() ) {

            $query->the_post();

            ?>

            <li <?php post_class( 'left' ); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
            </li>

            <?php
    
        }

    echo '</ul>';

}

// Restore original post data.
wp_reset_postdata();

?>

这将检查查询是否获取了任何帖子,如果是,它将打开ul 元素,然后运行该循环。

运行额外的循环

需要注意的是,虽然你可以使用WP_Query 来运行一个以上的循环,但你必须重置帖子数据,并启动第二个WP_Query 的实例才能做到这一点。这是因为你的每个循环都将根据不同的参数输出数据。

这个例子显示第一篇文章的摘录和特色图片,然后只显示每个后续文章的标题。

<?php

// First query arguments.
$args1 = array(
    'post_type' => 'post',
    'posts_per_page' => '1'
);

// First custom query.
$query1 = new WP_Query( $args1 );

// Check that we have query results.
if ( $query1->have_posts() ) {

    // Start looping over the query results.
    while ( $query1->have_posts() ) {

        $query1->the_post();

        ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php post_thumbnail( 'thumbnail' );?>
            </a>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php the_title(); ?>
            </a>
            <?php the_excerpt(); ?>
        </article>

        <?php

    }

}

// Restore original post data.
wp_reset_postdata();

// Second query arguments.
$args2 = array(
    'offset' => '1',
    'post_type' => 'post'
);

// Second custom query.
$query2 = new WP_Query( $args2 );

// Check that we have query results.
if ( $query2->have_posts() ) {

    echo '<ul class="more-posts">';
    
        // Start looping over the query results.
        while ( $query2->have_posts() ) {

            $query2->the_post();
    
            ?>

            <li <?php post_class(); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
            </li>
    
            <?php
    
        }
    
    echo '</ul>';

}

// Restore original post data.
wp_reset_postdata();

?>

我在这里使用了两个关键参数。

  • 'posts_per_page' => '1',与第一个查询一起使用,只输出最近的帖子。
  • 'offset' = '1',与第二个查询一起使用,跳过第一篇文章,确保它不会在下面的列表中重复。

从上面的代码可以看出,每个查询的循环略有不同。第一个输出特色图片、标题和摘录,而第二个则检查查询是否有帖子,如果有,则打开一个ul 元素,并将每个帖子的标题包含在一个li 元素中,并链接到其页面。

你还会注意到,我在两个循环之后都使用了wp_reset_postdata() 。如果我没有这样做,在我们的二级循环之外使用模板标签会给我提供循环内最后一个帖子的数据。调用这个函数可以将帖子数据重置到主查询中。

访问循环内的帖子信息

有很多函数可以在循环内调用,以便访问关于当前帖子的信息。你在本教程中也看到了其中一些函数的使用。在本节中,我将为你列出一些你可能会不时用到的常用函数。

获取标题

有三个函数可以用来获取文章的标题。它们是:the_title(),get_the_title(), 和the_title_attribute()get_the_title() 函数只是检索文章的标题,而the_title() 将显示或检索标题,并根据传递的参数进行可选的标记。当你想在显示标题之前对其进行消毒时,你应该使用the_title_attribute()

获取摘录或完整内容

有一个专门的函数叫the_excerpt() 来显示当前文章的摘录。它对所提供的摘录应用几个过滤器,以便它能正确地显示给浏览者。不是每篇文章都有作者提供的摘录。在这种情况下,它将在显示完整的帖子摘录之前生成一个修剪过的版本。

你可以通过使用函数the_content() 来显示帖子的完整内容。

获取帖子的类别、标签和其他元数据

你的WordPress帖子通常会有一些由你分配的标签或类别。你可以通过使用the_tags()the_category() 函数在循环中显示这些标签和类别的列表。使用the_author() 函数来显示帖子的作者。帖子的ID也可以用函数the_ID()

获取发布或修改日期和时间

在WordPress中有一些专门的函数,你可以在循环中使用这些函数来显示一个帖子的出版日期(the_date() )和时间(the_time() )。你应该记住的两个要点是:the_time() 也可以用来只显示一个帖子的出版日期。另外,对于在同一天发表的多个帖子,the_date() 的输出只被呼应一次。这基本上意味着,你几乎总是想使用the_time() ,以获得更大的灵活性和易用性。

总结

如果没有循环,WP_Query 其实并没有什么作用。循环是你用来显示WordPress根据你的查询参数从数据库中获取的数据的代码。

正如我所展示的,循环有几种变化。一个简单的循环将只是按照你在查询参数中指定的顺序输出所有的帖子(或者按照默认的降序日期)。如果你把if( $query->have_posts() )while( $query->have_posts() ) ,你可以在你的循环之外插入额外的标记,但只有在你的查询已经返回数据的时候。最后,通过指定替代参数并在每个循环后使用wp_reset_postdata() ,你可以多次使用WP_Query ,在你的页面上创建多个循环。