当前浏览:首页 / WordPress函数 / query_posts()

query_posts( array|string $query )

使用查询参数设置循环

postsmore...

querymore...


描述

注意:此函数将完全覆盖主查询,不适用于插件或主题。它修改主查询的过于简单的方法可能会有问题,应尽可能避免。在大多数情况下,有更好、更高性能的选项来修改主查询,例如通过WP_Query中的‘pre_get_posts’动作。

不能在WordPress循环中使用。


参数

$query

(array|string) (必填) WP_Query参数的数组或字符串。


返回

(WP_Post[]|int[]) post对象或post ID的数组。


说明

Flowchart illustrating why query_posts() should be avoided

Credit: Andrey Savchenko (rarst.net) / CC-By-SA.

query_posts()是一种改变WordPress用于显示文章的主查询的方法。它将主查询放在一边,并用一个新查询替换它。要在调用query_posts后进行清理,请调用wp_reset_query(),原始主查询将被还原。

应该注意的是,使用它来替换页面上的主查询可能会增加页面加载时间,在最坏的情况下,所需工作量会增加一倍以上。虽然该函数易于使用,但以后也容易出现混淆和问题。有关详细信息,请参阅下面的注意事项。

对于一般文章查询,请使用WP_Queryget_posts()

强烈建议您使用‘pre_get_posts’动作,并通过检查is_main_query()来更改主查询。

例如,在主页上,你通常会看到最近的10篇文章。如果您只想显示5篇文章(并且不关心分页),可以这样使用query_posts()

query_posts( 'posts_per_page=5' );

下面是在functions.php中使用‘pre_get_posts’动作的类似代码:

function wpdocs_five_posts_on_homepage( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 5 );
    }
}
add_action( 'pre_get_posts', 'wpdocs_five_posts_on_homepage' );

用法

// The Query
query_posts( $args );

// The Loop
while ( have_posts() ) : the_post();
	echo '
<li>';
	the_title();
	echo '</li>

';
endwhile;

// Reset Query
wp_reset_query();

循环开始之前,在一个模板文件中调用query_posts()WP_Query对象将使用您的参数生成一个新的SQL查询。执行此操作时,WordPress会忽略通过URL接收的其他参数(例如页码或类别)。

保留现有查询参数

如果要保留用于生成当前查询的原始查询参数信息,然后添加或覆盖某些参数,可以在对query_posts()的调用中使用$query_string全局变量。

例如,要在不影响查询字符串其余部分的情况下设置文章的显示顺序,可以将以下内容放在循环之前:

global $query_string;
query_posts( $query_string . '&order=ASC' );

以这种方式使用query_posts()时,参数的引用部分必须以与(&)开头。

或者,您可以将原始查询数组合并到参数数组中:

global $wp_query;
$args = array_merge( $wp_query->query_vars, array( 'post_type' => 'product' ) );
query_posts( $args );

参数组合

您可能已经从上面的一些示例中注意到,您将参数与符号(&)组合在一起,像这样:

query_posts( 'cat=3&year=2004' );

主页上当月类别13的文章:

if ( is_home() ) {
	query_posts( $query_string . '&cat=13&monthnum=' . date( 'n', current_time( 'timestamp' ) ) );
}

在2.3,这种组合将返回属于类别1和类别3的文章,只显示两(2)篇文章,按标题降序排列:

query_posts( array( 'category__and' => array(1,3), 'posts_per_page' => 2, 'orderby' => 'title', 'order' => 'DESC' ) );

下面返回所有属于类别1,标签为“apples”的文章。

query_posts( 'cat=1&tag=apples' );

您可以使用“+”搜索多个标签。在这种情况下,所有文章都属于类别1,标签为“apples”和“oranges”。

query_posts( 'cat=1&tag=apples+oranges' );

注意事项

query_posts()只是众多查询数据库和生成文章列表的方法之一。在决定使用query_posts()之前,请务必了解其缺点。

更改主循环

query_posts()用于改变主循环。它通过替换用于生成主循环内容的查询来实现。使用query_posts()后,与post相关的全局变量和模板标签将被更改。在您调用query_posts()之后调用的条件标签也将被更改–这可能是也可能不是预期的结果。

二次循环

要创建二次列表(例如,页面底部的相关文章列表,或边栏小工具中的链接列表),请尝试创建WP_Query的新实例或使用get_posts()

如果必须使用query_posts(),请确保在完成后调用wp_reset_query()

分页

除非适当设置“paged”查询变量,否则分页将无法正常工作。

额外的SQL查询

如果您在模板页面中使用query_posts,WordPress将已经执行了数据库查询,并在到达模板页面时检索到记录(这就是它如何知道要提供哪个模板页面!)。因此,当您使用query_posts()覆盖默认查询时,实际上是在丢弃默认查询及其结果,然后对数据库重新执行另一个查询。

这不一定是一个问题,尤其是如果你正在处理一个较小的基于博客的网站。具有大型数据库和高访问量的大型网站的开发人员可能希望考虑其他选择,例如直接修改默认请求(在调用之前)。‘request’过滤器可用于实现这一点。

‘parse_query’‘pre_get_posts’过滤器也可用于修改用于生成查询数据库的SQL的内部$query对象。



源码

查看源码 官方文档


更新日志

版本描述
1.5.0开始引入

使用示例

  • 示例1

    用特定类别中的所有文章覆盖主查询设置 > 阅读中的“博客页面最多显示”参数可能会影响结果。为了克服这个问题,添加posts_per_page参数。例如:

    query_posts( array(
    	'category_name'  => 'my-category-slug',
    	'posts_per_page' => -1
    ) );
    

    这将返回该类别中的所有文章。如果您有很多文章(数千篇),出于性能原因,请使用实际较高的数字,而不是-1。

    然而,对于子类别,category_name并不总是有效。而是使用category-slug。见is_category()

    if ( is_category( 'category-slug' ) ) : 
    	 query_posts( array(
    	 	'category_name'  => 'my-category-slug',
    		'posts_per_page' => -1
    	) ); 
    endif;
    

    使用-1时,同样的预防措施也适用。

  • 示例2

    将变量传递给query_posts可以根据需要使用多种方法将变量传递给查询。与其他示例一样,将这些放置在循环上方:

    示例1

    在本例中,我们在运行查询之前连接查询。首先分配变量,然后连接并运行它。这里我们从其他地方引入了一个类别变量。

    // assign the variable as current category
    $categoryvariable = $cat;
    
    // concatenate the query
    $args = 'cat=' . $categoryvariable . '&orderby=date&order=ASC';
    
    // run the query
    query_posts( $args );
    

    示例2

    在下一个示例中,双引号告诉PHP将封闭的作为表达式处理。在这个例子中,我们得到当前月份和当前年份,并告诉query_posts()为我们带来当前月份/年份的文章,在这种情况下,按升序列出,以便我们在页面顶部获得最旧的帖子。

    $current_year = date('Y');
    $current_month = date('m');
    
    query_posts( "cat=22&year=$current_year&monthnum=$current_month&order=ASC" );
    

    例3

    这个例子解释了如何生成一个完整的文章列表,处理分页。我们可以使用默认的$query_string告诉query_posts()给我们带来完整的文章列表。我们还可以将posts_per_page查询参数从-1修改为您希望在每个页面上显示的文章数;在最后一种情况下,您可能希望使用posts_nav_link()来导航生成的存档。

    query_posts( $query_string . '&posts_per_page=-1' );
    

    例4

    如果您不需要使用$query_string变量,那么在一些更复杂的情况下,还有另一种方法更清晰可读。该方法将参数放入数组中。与上面示例2中相同的查询可以这样完成:

    $args = array(
    	'cat'      => 22,
    	'year'     => $current_year,
    	'monthnum' => $current_month,
    	'order'    => 'ASC'
    );
    query_posts( $args );
    

    如您所见,通过这种方法,每个变量都可以放在自己的行上,以便于阅读。

    例5

    甚至可以使用数组样式(示例4)来查询多个分类。只需为taxonomy slug提供一串逗号分隔的值(每个值都是一个term)。在下面的例子中,我们将获得由Bruce Campbell或Chuck Norris主演的所有电影文章。

    $args = array(
    	'post_type'=> 'movie',
    	'actor'    => 'Bruce Campbell, Chuck Norris',
    	'order'    => 'ASC'
    );
    query_posts( $args );
    
  • 示例3

    将此代码放入index.php文件将导致主页显示除类别ID 3之外的所有类别的文章。

    if ( is_home() ) {
    	query_posts( 'cat=-3' );
    }