如果您过去构建过简单的主题,可能没有需要自行检索文章的情况。毕竟,WordPress 会在主页上加载最新的十篇文章,在归档页上加载正确的文章。那么更复杂的场景呢?如果您想要某种站点地图,想要列出按日期排序的所有文章和页面?
WP_Query 是您的朋友,它允许您根据您的条件从数据库中检索文章。您可以检索包含某些标签的单个分类的所有文章。您也可以检索去年创建的所有页面以及没有缩略图的文章。
在这篇文章中,我将深入了解 WP_Query 的工作原理——让我们开始吧!

自定义循环
使用自定义查询的关键在于掌握可以传递给它们的参数。在了解这一点之前,让我们创建一个可以用来列出文章的快速”框架”。常规归档页面上的循环类似于这样:
<?php if ( have_posts() ) : ?>
<?php while( have_posts() ) : the_post() ?>
<!-- Display Post Here -->
<?php endwhile ?>
<?php else : ?>
<!-- Content If No Posts -->
<?php endif ?>Code language: HTML, XML (xml)
这完全没问题,因为在页面加载之前,WordPress 已经检索到了正确的文章。当我们编写自定义查询时,我们需要一个自定义循环。代码非常相似,如下所示:
<?php
$args = array(
'post_type' => 'post',
'post_status' => 'future'
);
$scheduled = new WP_Query( $args );
if ( $scheduled->have_posts() ) :
?>
<?php while( $scheduled->have_posts() ) : $scheduled->the_post() ?>
<!-- Display Post Here -->
<?php endwhile ?>
<?php else : ?>
<!-- Content If No Posts -->
<?php endif ?>Code language: HTML, XML (xml)
我们使用 WP_Query 类创建一个新的 WordPress 查询,向它传递参数以指定我们需要的内容类型。然后在我们的 $scheduled 对象上调用 have_posts() 和 the_post() 方法。
如果您不熟悉面向对象编程,不明白为什么是这样,别担心,您仍然可以轻松使用自定义查询。我们将在整篇文章中关注 $args 数组,它非常简单。
简单参数
正如我提到的,WP_Query 的主要”知识体系”在于它的参数。Codex 列出了所有参数,我们将在这里查看最有用的参数。
一些参数非常简单,比如 tag 或 tag_id 参数。前者接受标签别名,后者接受标签 ID。您也可以用逗号分隔多个项目,或者使用负 ID 来表示您想要检索没有附加该特定标签的文章。
$args = array(
'post_type' => 'post',
'tag_id' => '22,92,44,-21'
);
$our_posts = new WP_Query( $args );Code language: PHP (php)
这段代码会检索带有前三个标签中任意一个的文章,但不包含第四个标签。虽然这个系统对于简单需求已经足够强大,但我通常使用更灵活的分类法查询,我将在后面稍作讨论。
author、author_name、cat、category_name、s(用于搜索词)、post_status、post_type 都是一些更简单字段的例子。请注意,有些字段(如 post_status)如果需要使用多个值,需要传递一个数组。
$args = array(
'post_type' => array( 'post', 'page' ),
'post_status' => array( 'draft', 'publish' ),
'cat' => 'music,videos'
);
$our_posts = new WP_Query( $args );Code language: PHP (php)
上面的示例检索的是页面或文章、已发布或草稿状态、属于音乐或视频分类的文章。这可用于显示当前或计划中的与音乐或视频相关的内容标题。
分类法查询
对于简单需求,使用上述参数根据分类或标签检索文章已经足够,但如果你有自定义分类法,或者需要组合多个参数该怎么办?答案就在于 tax_query 参数,它本身就是一个数组。让我们先看一个例子。
$args = array(
'post_type' => 'book',
'tax_query' => array(
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => array( 'scifi', 'thriller' ),
'operator' => 'NOT IN',
),
array(
'taxonomy' => 'author',
'field' => 'id',
'terms' => array( 92, 883, 399 ),
),
'relation' => 'AND',
),
);
$query = new WP_Query( $args );Code language: PHP (php)
这里我们从“book”文章类型中检索一些文章,并添加了一些分类法参数。通过在 tax_query 中定义的两个数组,我们指定要获取作者 ID 为 92、883 或 399 的书籍,但不在科幻或惊悚分类中。relation 参数定义了两个数组之间的关系。在我们的例子中,这是“and”关系,意味着两个条件都必须满足。
如果我们使用“or”,我们就会检索不在科幻或惊悚分类中的书籍,或者由指定的三位作者撰写的书籍。用通俗的话来说就是:我想看我所有的书,但不包括科幻和惊悚分类。不过,我想看到特里·普拉切特、道格拉斯·亚当斯和斯蒂芬·金的所有作品,无论是什么类型。
元查询
元查询在结构上与分类法查询非常相似,但它们使用文章元表中的数据来过滤文章。以下代码将显示所有带有特色图片的已发布文章。
$args = array(
'post_type' => 'post',
'meta_query' => array(
array(
'key' => '_thumbnail_id',
'value' => '',
'compare' => '!=',
),
),
);
$query = new WP_Query( $args );Code language: PHP (php)
WordPress 使用 _thumbnail_id 字段存储文章的特色图片 ID。因此,如果我们检索所有此元值不为空的文章,应该就能得到所有带有特色图片的文章。
这里的秘诀在于了解如何使用 compare 属性和 type。你可以使用许多在 SQL 中应该很熟悉的值:’=’、’!=’、’>’、’>=’、'<‘、'<=’、’LIKE’、’NOT LIKE’、’IN’、’NOT IN’、’BETWEEN’、’NOT BETWEEN’、’EXISTS’(从 WordPress 3.5 开始)和 ‘NOT EXISTS’(从 WordPress 3.5 开始)
type 属性通常在比较数字或日期时很重要。可能的值有 ‘NUMERIC’、’BINARY’、’CHAR’、’DATE’、’DATETIME’、’DECIMAL’、’SIGNED’、’TIME’、’UNSIGNED’。请记住,在比较数字时要使用 NUMERIC,在大多数其他情况下应该没问题。
就像分类法查询一样,你可以堆叠多个需求,然后使用 relation 参数来指定它们之间的关系。
$args = array(
'post_type' => 'post',
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'mood',
'value' => array( 'happy', 'awesome' ),
'compare' => 'IN',
),
array(
'key' => 'income',
'value' => 500,
'compare' => '>',
'type' => 'NUMERIC'
),
),
);
$query = new WP_Query( $args );Code language: PHP (php)
上面的例子将显示来自假设日记的帖子,其中发生了好事。我要么感到快乐或棒极了,要么那天我赚了超过500美元。
日期参数
日期可能会变得有些复杂,但非常灵活。如果您需要更多信息,WP_Query文档有很多示例。
从某个时间检索帖子非常容易。您可以使用year、monthnum、w(一年中的第几周)、day和其他几个参数来指定时间。下面的代码将检索2013年3月的所有帖子。
$args = array(
'post_type' => 'post',
'year' => 2013,
'month' => 3
);
$query = new WP_Query( $args );Code language: PHP (php)
如果您需要更复杂的时间范围,则需要使用date_query。这允许您使用熟悉的数组格式轻松指定任意范围。下面的示例(来自Codex)展示了如何检索工作日在上午9点到下午5点之间发布的帖子。
$args = array(
'post_type' => 'post',
'date_query' => array(
array(
'hour' => 9,
'compare' => '>=',
),
array(
'hour' => 17,
'compare' => '<=',
),
array(
'dayofweek' => array( 2, 6 ),
'compare' => 'BETWEEN',
),
),
);
$query = new WP_Query( $args );Code language: PHP (php)
排序结果
列表中元素的呈现顺序与列表中的元素本身同样重要。幸运的是,WordPress为我们提供了order_by和order参数。order参数非常 straightforward,您可以使用ASC或DESC来升序或降序排序。
order_by参数可以接受多个值:’none’、’ID’、’author’、’title’、’name’、’type’、’date’、’modified’、’parent’、’rand’、’comment_count’、’menu_order’、’meta_value’、’meta_value_num’、’post__in’。按meta_value排序尤其有用。在这种情况下,别忘了还要指定meta_key字段。
$args = array(
'post_type' => 'painting',
'meta_query' => array(
array(
'key' => 'price',
'value' => 50000,
'compare' => '>',
'type' => 'NUMERIC'
),
),
'order_by' => 'meta_value_num',
'meta_key' => 'price'
);
$query = new WP_Query( $args );Code language: PHP (php)
此示例检索价值超过50,000美元的画作,并按价格升序排序。请注意,由于价格存储为数字,我使用meta_value_num来排序结果,而不是用于字符串的meta_value。
另一个值得一说的排序方式是post__in。这个post__in是一个独立的参数,它允许您指定要检索的文章ID数组。默认情况下,WordPress按日期对帖子排序,post__in中指定的顺序不会被保留。如果您也使用post__in作为order by的值,WordPress将保留该顺序。
$args = array(
'post_type' => 'post',
'post__in' => array( 23, 441, 12, 322, 34, 33),
'order_by' => 'post__in',
);
$query = new WP_Query( $args );Code language: PHP (php)
总结
希望从这个WP_Query介绍中可以看出,这确实是一个强大的类。它允许您使用自己的条件以WP标准方式检索帖子。请查看其文档以获取更多信息以及此类提供的用于操作查询和循环的优秀属性和方法。
WP_Query 是 WordPress 成为优秀通用 CMS 的部分原因——它能够以模块化和可定制的方式从数据库中检索对象。



