以下是 Christian Nolen 的客座文章。Christian 详细介绍了一种情况,在这种情况下,数据正在以智能和合理的方式组织,但对于精确查询来说却有点棘手。他详细介绍了一种解决方案,该解决方案不会过于深入细节,以确保正确性。
如果您曾经进行过任何 WordPress 开发,您可能需要创建自定义帖子类型 和 注册分类法。当关系是一对一时,处理分类法非常简单,即“获取所有分类法术语,使用 get_terms()
,或获取与当前帖子关联的所有术语,使用 get_the_terms()
。”
但是,当您需要返回的结果相对于另一个分类法时该怎么办?这两个典型函数都没有帮助。在深入探讨解决方案之前,让我们仔细看看问题。用例是提供多种服务和多个市场的投资组合网站
- 自定义帖子类型:投资组合
- 分类法:服务
- 术语:开发、插图、摄影、印刷设计、网页设计
- 分类法:市场
- 术语:公民、企业、教育、健康、非营利组织
此网站需要对服务和市场都使用分类法模板。当访问者访问这些分类法页面之一时,将显示一个选项卡布局,显示关联市场的投资组合项目(如果查看服务)或关联的服务(如果查看市场)。

在上面的屏幕截图中,我正在显示一个摄影服务页面。我已使用get_terms('market')
检索有效的市场(分配给$markets
变量)。我遍历每个市场以创建我的选项卡,然后使用WP_Query
检索所有相应的投资组合项目。tax_query
参数用于将结果缩小到当前市场和服务(在这种情况下使用get_query_var('term')
定义)。
我们首先注意到一个令人尴尬的空“公民”选项卡,它突出了服务在此市场中未提供的这一事实。此外,这是访问者在此页面上看到的第一个选项卡。
解决方案
我花费了大量时间研究解决方案。我找到的唯一解决方案涉及使用 wpdb 查询数据库。是的,这是一个解决方案,但感觉不太对。我知道一定有内置方法来处理此用例。
在深入研究 WordPress Codex 后,我发现了wp_get_object_terms()
。该函数的描述如下
检索与提供的分类法中给定对象关联的术语。
提供的示例非常类似于您在get_the_terms()
中找到的示例。关键是对象参数可以是数组。
我们要传递给wp_get_object_terms()
的对象是帖子 ID 数组。我能想到构建此数组的最有效方法是使用get_posts()
,并将fields参数设置为“ids”。您可以使用WP_Query
,但我选择使用get_posts(),因为
get_posts()
返回数组而不是对象- 我永远不会将我的初始
get_posts()
调用与选项卡内容中使用的WP_Query
混淆。
$service_slug = get_query_var('term');
$service_post_IDs = get_posts(array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'service',
'field' => 'slug',
'terms' => $service_slug
)
),
'fields' => 'ids'
));
以上是如何获取正确的帖子 ID 子集的方法。如前所述,我通过使用get_query_var('term')
检索当前服务 slug 并将其分配给$service_slug
变量。这在tax_query
中用于确保我们仅获取分配给当前分类法术语的帖子 ID。通过将fields
参数设置为ids
,结果将是帖子 ID 的索引数组。
现在我已经有了帖子 ID 数组,我可以将get_terms()
替换为以下内容
$markets = wp_get_object_terms($service_post_IDs, 'market');
刷新页面后,“公民”选项卡消失了,我们有一个填充了正确内容的选项卡。

我可以就此停止。但现在WP_Query
中使用的参数让我感到困扰。
$args = array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'market',
'field' => 'slug',
'terms' => $m->slug,
),
array(
'taxonomy' => 'service',
'field' => 'slug',
'terms' => $service_slug,
),
)
);
是的,以上方法可以正常工作。但我觉得我在tax_query
方面重复了工作。我们可以做的是重构tax_query,使其仅包含当前市场,并利用post__in
参数以及服务帖子 ID 数组。
$args = array(
'post_type' => 'portfolio',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'market',
'field' => 'slug',
'terms' => $m->slug,
)
),
'post__in' => $service_post_IDs
);
前端结果相同,但现在查询参数更简洁易读。最重要的是,您现在拥有一个向访问者显示有效信息的模板。
很高兴我抛弃了 WP 那堆东西。
Jekyll 获胜!
您是否也可以在
get_terms
中使用hide_empty
参数?不可以,因为“hide_empty”仅隐藏分配了 0 个帖子的术语。
他需要隐藏当前帖子未分配给它的术语 - 但可能还有其他帖子分配给了它,在这种情况下,hide_empty 不会起作用。
无论如何,最好是精确而不是尝试查找仅在当前用例中有效的变通方法。
干得好!!
我将尝试您的解决方案,希望它也能为我工作。
谢谢
太棒了!我目前正在使用通过 wpdb 的巨型查询来实现类似的功能。
此解决方案是否适用于分层和非分层分类法,例如类别和标签?
当然可以。它适用于任何分类法。
这太棒了,简直是梦想成真!我花了几个小时寻找解决方案!谢谢
这比你想象的更有帮助。非常感谢!