在 "掌握WP_Query"系列的这一部分,你将了解一些你可以在WP_Query 类中使用的参数,即用于状态、顺序和分页的参数。
你可以使用这些参数从数据库中获取预定的帖子,查询附件,修改帖子的排序方式和排序内容,指定显示多少个帖子,以及更多。
但是在你做这些之前,你需要了解参数在WP_Query 。
回顾一下参数在WP_Query 中是如何工作的
在我们开始之前,让我们快速回顾一下参数在WP_Query 中是如何工作的。当你在你的主题或插件中编写WP_Query ,你需要包括四个主要元素:
- 查询的参数,使用本教程将涉及的参数
- 查询本身
- 循环
- 结束:关闭if和while标签并重设帖子数据
在实践中,这将看起来像下面的东西:
<?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();
?>
参数是告诉WordPress要从数据库中获取什么数据,我在这里要讲的就是这些。所以,我们在这里所关注的是代码的第一部分:
$args = array(
// Arguments for your query.
);
正如你所看到的,参数被包含在一个数组中。在你学习本教程时,你将学会如何为它们编码。
参数的编码
对数组中的参数进行编码有一个特定的方法,如下所示:
$args = array(
'parameter1' => 'value',
'parameter2' => 'value',
'parameter3' => 'value'
);
你必须用单引号括住参数和它们的值,在它们之间使用=> ,并用逗号分开。如果你弄错了,WordPress可能不会把所有的参数加到查询中,或者你可能会得到一个白屏。
状态参数
正如你知道的,如果你曾经把一个帖子的状态从草稿转为发布,或者也许把它放在垃圾桶里,WordPress会给每个帖子分配一个状态。你可以使用post_status 参数来查询具有一个或多个状态的帖子。
可用的参数有:
publish:一个已发表的帖子或页面pending:帖子正在等待审查draft: 处于草稿状态的帖子auto-draft:新创建的帖子,没有内容future: 将在未来发布的帖子private: 未登录的用户不可见inherit: 正在修改trash: 帖子在垃圾箱中any: 任何状态,除了那些设置为 "exclude_from_search"的帖子状态(即:inherit,trash, 和auto-draft)。任何你将exclude_from_search设置为 "true "的自定义帖子状态也将被排除在结果之外。
如果你没有在你的查询参数中指定一个状态,WordPress将默认为publish ;如果当前用户已经登录,它也将包括状态为private 的帖子。如果你在管理页面运行查询,WordPress也将包括受保护的状态,默认为future 、draft 和pending 。
inherit 状态同时适用于附件和修订。在编辑界面上传的媒体文件是附在我们正在编辑的当前帖子上的。因此,它们的状态与父帖子的状态相同是有道理的。同样,对一个帖子的修订也使用inherit ,因为它们的状态应该与父帖子同步。
所以,假设你正在运行一个活动网站,你正在使用一个自定义的事件帖子类型,使用发布日期作为事件发生的日期。默认情况下,WordPress不会显示任何还没有发生的事件:虽然你已经安排了它们,但它们的预定日期是在未来,所以它们的帖子状态是未来。
为了解决这个问题,你只需使用这些参数:
$args = array(
'post_type' => 'event',
'post_status' => 'future'
);
这将只显示那些还没有发生的事件,因为这些事件的状态是publish 。但如果你也想显示已经发生的事件,你可以使用一个帖子状态的数组来包括一个以上:
$args = array(
'post_type' => 'event',
'post_status' => array(
'future',
'publish'
)
);
当你查询附件的时候,post_status 这个参数是必不可少的。否则,你将得到一个空列表。这是因为它们的状态是inherit ,而不是publish 。因此,要查询所有的附件,你应该使用这个:
$args = array(
'post_type' => 'attachment',
'post_status' => 'inherit'
);
另外,你可以用any 替换inherit ,这将有同样的效果。下面是我运行上述查询后得到的结果。
你可能对我们查询中指定的帖子状态和检索结果不匹配感到困惑。发生这种情况是因为附件返回的是其父辈的帖子状态。在这种情况下,所有这些帖子恰好都是已发布的。
排序参数
有两个参数可以用来排列由WP_Query 检索的帖子:order 和orderby 。正如你所期望的那样,order 定义了帖子在循环中输出的顺序,而orderby 则定义了它们在数据库中被排序的字段。
让我们先看一下order 的参数。
order 参数
你可以用两个参数来做这个:
ASC: 从低到高的升序(1,2,3;a,b,c)。DESC: 从高到低的降序(3, 2, 1; c, b, a)。
这些都是相当不言自明的。如果你不包括order 的参数,WordPress将默认为DESC 。你也可以传递一个数组来创建多个order/orderby对进行排序。
orderby 参数
你可以通过一系列的字段对你的帖子进行排序:
none: 不排序ID:按帖子的ID排序(注意大写)。author: 按作者排序title:按标题排序name: 按帖子标题排序type按帖子类型排列:按帖子类型排列date按日期排列:按日期排列modified按最后修改日期排序parent按帖子或页面的父ID排序rand: 随机排序comment_count按评论数排序:按评论数排序relevance: 按搜索词排序。优先考虑全句匹配。之后,我们转到标题中的所有搜索词,标题中的一些搜索词,以及帖子中的搜索词。menu_order:按页面顺序排列。最常用于页面(使用你在编辑页面屏幕中添加到元框的值)和附件(使用媒体库对话框中的整数字段),但可以用于任何启用menu_order的帖子类型。meta_value按元键(或自定义字段)的值排序。这只有在你的参数中还包括meta_key参数时才有效。元值是按字母排序的,而不是按数字排序的(例如,34会排在4之前)。meta_value_num顺序:按数字元值排序。与meta_value一样,你也必须在你的查询中包括一个meta_key参数。post__in: 保留在post__in阵列中给出的帖子ID顺序。post_name__in: 保留在post_name__in数组中给出的帖子slug顺序post_parent__in:保留在post_parent__in数组中给出的帖子父级顺序
最后两个选项从WordPress 4.6开始可用。请记住,当你使用post__in,post_name__in, 和post_parent__in 选项时,order 的参数值会被忽略。
默认值是date ,即文章发表的日期。
因此,例如,如果你想按标题升序排列你的帖子,你可以使用这些参数:
$args = array(
'orderby' => 'title',
'order' => 'ASC'
);

第一篇文章对你来说会显得不合适。它不符合顺序的原因是它是一个粘性帖子,而粘性帖子在列表的开头,因为分页参数ignore_sticky_posts ,默认设置为false 。
按多个字段排序
你不必拘泥于只按一个字段对你的帖子进行排序。要按多个字段排序,你可以使用一个数组,使用orderby 参数,如果你想按不同的顺序对每个字段进行排序,可以选择使用order 参数。
因此,假设你有一个 "评级 "自定义字段,你想在电子商务网站或博客文章列表中使用它来进行排序。你可以先按评分排序,然后再按标题排序,都是降序排列,这样就可以了:
$args = array(
'orderby' => 'meta_value_num title'
'order' => 'DESC',
'meta_key' => 'ratings_score'
);
注意,我已经包括了meta_key 参数,以便让WordPress知道我在使用哪个自定义字段。你这样做是因为WordPress存储帖子元数据的方式:不是在wp_posts 表,而是在wp_postmeta 表。
上面的参数将首先按评分分数从高到低排序所有的帖子,然后具有相同评分分数的帖子将按其标题从高到低排序。

但是,如果你想按评分降序排序,然后按标题升序排序呢?你只需使用另一个数组:
$args = array(
'orderby' => array(
'meta_value_num' => 'DESC',
'title' => 'ASC'
),
'meta_key' => 'ratings_score'
);

当不使用帖子元数据时,你也可以按多个字段排序,例如,按帖子类型排序,然后按日期排序:
$args = array(
'orderby' => array(
'type' => 'ASC',
'date' => 'DESC'
)
);
分页参数
下一组参数是用于分页的。这些参数帮助你定义有多少帖子将被查询,以及当它们被输出时如何进行分页。
可用的参数有:
nopaging(布尔型):显示所有帖子或使用分页。默认是'false',即使用分页。posts_per_page(int): 每页要显示的帖子数量posts_per_archive_page(int): 每页显示的帖子数量--仅在档案页上显示offset(int):替换或越过的帖子数量paged(int): 在档案中显示帖子的页面page(int): 静态首页的页数。显示通常只在静态首页的第X页上显示的帖子。ignore_sticky_posts(boolean):忽略帖子的粘性-默认为false
让我们看一下一些例子:
帖子的数量和偏移的帖子
例如,要显示最近的五个帖子:
$args = array(
'posts_per_page' => '5'
);

我们会自动得到最近的五个帖子,因为orderby 参数的值默认设置为date ,这一点我们在上一节中已经学到了。同样,你可能已经注意到,即使粘性帖子不是最近的,它也会保持在顶部。它也在我们的五个帖子中占了一个位置。你可以告诉WordPress忽略粘性帖子,正如我们将在下面看到的。
或者显示五个最近的帖子,不包括最近的一个:
$args = array(
'posts_per_page' => '5',
'offset' => '1'
);
尽管你是从数据库中最近的六个帖子中获取帖子,但你仍然使用'posts_per_page' => '5' ,因为那是将被输出的帖子的数量。
再进一步,你可以写两个查询:一个是显示最近的帖子,另一个是显示除该帖子之外的另外十个帖子:
$args = array(
'posts_per_page' => '1'
);
// Query and loop go here as well as resetting posts.
$args = array(
'posts_per_page' => '10',
'offset' => '1'
);
// Second query, loop, and resetting go here.
你也可以使用posts_per_page 来显示所有的帖子:
$args = array(
'posts_per_page' => '-1'
);
粘性帖子
通常情况下,你的粘性帖子会在任何查询中优先显示:如果你想覆盖这一点,使用ignore_sticky_posts:
$args = array(
'posts_per_page' => '5',
'ignore_sticky_posts' => true
);
上述参数将返回最近的五个帖子,不管它们是否是粘性的:

注意,如果你想只显示粘性帖子,你需要使用get_option() 函数和post__in 参数,如下所示:
$sticky = get_option( 'sticky_posts' );
$args = array(
'posts_per_page' => '5',
'post__in' => $sticky
);
get_option() 函数将返回一个粘性帖子ID的数组,并将其传递给post__in 参数。以上将显示最后五个粘性帖子。如果少于五个(例如三个)粘性帖子,它不会显示非粘性帖子,而只是显示最近的三个粘性帖子。
档案中的分页
除了定义从数据库中获取多少帖子之外,你还可以使用分页参数来定义所产生的帖子在存档和搜索页面上的分页方式。
因此,举例来说,在归档页上,你可以使用这段代码,在归档页上每页显示20篇文章:
$args = array(
'posts_per_archive_page' => '20'
);
posts_per_archive_page 参数将在所有页面上覆盖posts_per_page ,其中is_archive() 和is_search() 返回true 。
你也可以选择只输出在分页中会出现在某个页面的页面。因此,举例来说,如果你想显示上面例子中第三页上的20个帖子,你就可以使用这个参数:
$args = array(
'posts_per_archive_page' => '20',
'paged' => '3'
);
另一种查询相同帖子的方法是使用offset 参数:
$args = array(
'posts_per_page' => '20',
'offset' => '40'
);
这就跳过了前40个帖子(这些帖子将出现在前两个档案页上),而获取下一个20个帖子(这些帖子将出现在第三个档案页上)。我喜欢WordPress的一个原因是,它经常给你一个以上的方法来实现某件事情。
你也可以完全关闭分页,以确保所有的文章都显示在同一页面:
$args = array(
'nopaging' => true
);
总结
WP_Query 类在决定你想查询多少个帖子、你想以什么顺序显示它们、以及你想显示什么状态的帖子时,给了你足够的灵活性。
其中一些参数对于查询某些类型的帖子是必不可少的(例如,'post_status' => 'inherited' 的附件),而其他参数只是让你对查询的运行方式有更多的控制。
通过使用这些参数,你可以创建自定义查询,而不是简单地输出最近发布的帖子。