返回介绍

query_posts()

发布于 2017-09-11 10:02:13 字数 9221 浏览 1100 评论 0 收藏 0

query_posts( array|string $query )

根据传入的参数,重置整个 WordPress 的查询条件。


description

注意:这个函数推荐在主题或者插件中使用,在后面的介绍中,有更好的更高性能的可选函数和方法来改变 WordPress 主查询,query_posts() 通过重置主查询的参数来改变查询结果,这是一种危险而简单的解决方法,它是低效的(重新运行SQL查询)和在某些情况下会彻底失败(尤其是经常在处理文章分页)。任何WordPress的参考函数应该使用更可靠的方法,如利用 pre_get_posts hook等。

注意:query_posts() 必须用于  WordPress 的 Loop 循环里面,使用完成以后,一定要使用 wp_reset_query() 函数重置 WordPress 的主查询。


参数

$query
(array|string)
(Required)
Array or string of WP_Query arguments.

返回值

返回一个 post 对象的数组,如果查询为空,则返回一个空数组。


源代码

File: wp-includes/query.php

function query_posts($query) {
	$GLOBALS['wp_query'] = new WP_Query();
	return $GLOBALS['wp_query']->query($query);
}

更新日志

Versiondescription
1.5.0Introduced.

更多信息

query_posts() 是一种改变 WordPress 主查询来显示文章的函数。它通过把主查询放在一个一边,然后用一个新的查询替换它,来实现自定义查询参数。在每次调用 query_posts 函数以后,都需要通过 wp_reset_query() 重置原来主查询结果。 应该注意的是,使用此替换页面上的主查询可以增加页面载入时间,在最坏的情况下,增加一倍以上所需的工作量。虽然使用方便,但功能也容易出现混乱和问题。看下面的细节进一步说明注意事项。 对于一般文章的查询,使用 WP_Query 或者 get_posts 即可。 强烈建议您使用 pre_get_posts 过滤查询结果,和通过 is_main_query 检查和改变主查询例如,在网页上,你通常会看到最新的 10 篇文章。如果你只想显示 5 篇文章(不关心分页),你可以用 query_posts() 像这样写:

query_posts( 'posts_per_page=5' );

他类似于使用 pre_get_posts 在 functions.php 通过Action 过滤条件:

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' );

注:pre_get_posts 动作无法正常工作于 页面(Page)查询。

使用方法

// 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 。 例如,要修改文章的显示顺序并且不影响接下来的查询,你可以在循环(The Loop)前面使用下面的代码:

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' );

在首页查询当前月份的分类ID为 13 的文章:

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

下面的例子,将返回一组文章(分类ID为 1 和 3 、显示 2 篇文章、根据标题降序排列):

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

下面的例子将返回分类ID为 1 和 标签为 “apples”的文章:

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

你可以使用加号 + 来添加更多标签:

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

注意事项

query_posts() 只是一种查询数据库获取文章列表的方法。在使用 query_posts() 之前,你需要了解它的弊端。

改变主循环(Alters Main Loop)

query_posts() 是通过替换查询条件来改变主循环生成的内容的。一旦你使用 query_posts(), 你文章的相关的全局变量和模板标签都将改变。条件标签(Conditional tags)在你调用 query_posts() 之后也会发生改变——这可能是也可能不是预期的结果。

二级循环(Secondary Loops)

要创建 二级列表(例如:在页面底部显示相关文章列表,或者在边栏小工具中显示一个列表), 尝试使用 WP_Query 或 get_posts() 来获取文章。 如果你一定要用 query_posts() ,请确保你在上一个使用了 query_posts() 的循环结束的地方,使用 wp_reset_query() 来重置查询。

分页(Pagination)

分页将无法正常工作,除非你适当设置 ‘paged’ 查询

额外的SQL查询

如 果你在模板页面中使用 query_posts ,WordPress 就会在 query_posts 时执行数据库查询和检索记录(即它是如何知道是服务于哪个模板页面!)所以,当你使用 query_posts() 覆盖了默认的查询,你基本上就扔掉了默认的查询以及它的结果,并重新对数据库执行了另一个查询。 这也许不是一个问题,尤其是如果你正在处理一个较小的基于博客的网站。但是对于大型网站、大型数据库以及较高的访客流量来说,你就要考虑使用其他查询方式来减少 SQL查询了,比如直接修改默认的查询(在它被请求前)。使用请求(request)过滤器可是实现这点。 ‘parse_query’ 和 ‘pre_get_posts’ 过滤器也可用来修改内部用于生成SQL查询数据库的 $query 对象。

源代码

  • For more in-depth discussion of how WordPress generates and handles its queries, review these articles: Query Overview and Custom Queries
  • Customize the Default Query properly using ‘pre_get_posts’ – Bill Erickson – Customize the WordPress Query or John James Jacoby – Querying Posts Without query_posts
  • You don’t know Query – Slides from WordCamp Netherlands 2012 by Andrew Nacin

相关函数

Uses

  • wp-includes/class-wp-query.php:WP_Query::__construct()

重置特定分类中的主查询

默认情况下,WordPress 会显示 10 篇文章,这个可以再后台的设置-阅读里面设置,但是如果我们只想在某个分类下面显示所有的文章,那么我们可以这样编写代码:

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

posts_per_page 参数用于设置显示文章的数量,如果设置为 -1 ,那么就是显示所有的文章,如果你又很多的文章,不建议这样设置。

然后如果是在子分类页面,可能上面的代码会出现一点问题,所以我们先判断一下是否是某个特定的分类。

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

在首页排除分类

将下面的代码添加到 index.php 文件,这样首页将显示 除了分类ID为 3 以外的其他所有文章:

<?php
if ( is_home() ) {
	query_posts( 'cat=-3' );
}
?>

你还可以以此类推添加更多要排除的分类:

<?php
if ( is_home() ) {
	query_posts( 'cat=-1,-2,-3' );
}
?>

检索某一篇文章

要检索某一篇文章,可以使用下面的代码:

query_posts( 'p=5' );

注:如果检索的是一个附件,那你应该使用 attachment_id 代替 p :

query_posts( 'attachment_id=5' );

如果你想使用“阅读更多(Read More)”功能,你就需要在查询中设置全局变量 $more 的值为 0 :

<?php
// retrieve one post with an ID of 5
query_posts( 'p=5' );

// set $more to 0 in order to only get the first part of the post
global $more;
$more = 0;

// the Loop
while (have_posts()) : the_post();
	the_content( 'Read the full post »' );
endwhile;
?>

一个分类的所有文章

在 设置 > 阅读 中,“博客页面最多显示”的设置可以影响你的结果。为了克服这个问题,你可以添加 ‘posts_per_page’ 参数,例如:

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

这样将显示这个分类的所有文章。 但是,对于子分类(subcategories or child categories), ‘The Category Name’ 可能就没办法生效,请使用 ‘category-slug’ 替代。阅读 Function_Reference/is_category

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

聚合 Feeds

在 设置 > 阅读 中,“Feed 中显示最近”的设置 或者 ‘posts_per_rss’ 参数将在 Feed 中覆盖任何查询的 ‘posts_per_page’ 参数。 为了克服这个问题(例如在自定义的 ics Feed 中,输出所有符合条件的文章),可以使用 “posts_limit” 过滤器:

if ( isset ( $query->query_vars['feed'] ) and ( $query->query_vars['feed'] == 'ics' ) )
{
	add_filter( 'post_limits', '__return_empty' );
}

传递变量到 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() 显示当前 年/月 的文章。此外,我们使用升序排列(ASE) ,这样,最老的文章将显示在页面的顶部:

$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),多个别名使用逗号隔开。在下面的例子中,我们会得到 Bruce Campbell 或 Chuck Norris 的movie文章:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文