获取与不同分类相关的 WordPress 术语结果

Avatar of Christian Nolen
Christian Nolen 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

以下是 Christian Nolen 的客座文章。Christian 详细介绍了一种情况,在这种情况下,数据正在以智能和合理的方式组织,但对于精确查询来说却有点棘手。他详细介绍了一种解决方案,该解决方案不会过于深入细节,以确保正确性。

如果您曾经进行过任何 WordPress 开发,您可能需要创建自定义帖子类型注册分类法。当关系是一对一时,处理分类法非常简单,即“获取所有分类法术语,使用 get_terms(),或获取与当前帖子关联的所有术语,使用 get_the_terms()。”

但是,当您需要返回的结果相对于另一个分类法时该怎么办?这两个典型函数都没有帮助。在深入探讨解决方案之前,让我们仔细看看问题。用例是提供多种服务和多个市场的投资组合网站

  • 自定义帖子类型:投资组合
  • 分类法:服务
  • 术语:开发、插图、摄影、印刷设计、网页设计
  • 分类法:市场
  • 术语:公民、企业、教育、健康、非营利组织

此网站需要对服务市场都使用分类法模板。当访问者访问这些分类法页面之一时,将显示一个选项卡布局,显示关联市场的投资组合项目(如果查看服务)或关联的服务(如果查看市场)。

Screenshot of tab layout with the first tab empty

在上面的屏幕截图中,我正在显示一个摄影服务页面。我已使用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(),因为

  1. get_posts()返回数组而不是对象
  2. 我永远不会将我的初始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');

刷新页面后,“公民”选项卡消失了,我们有一个填充了正确内容的选项卡。

Screenshot of how the corrected tab layout - without empty tab Civic

我可以就此停止。但现在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
);

前端结果相同,但现在查询参数更简洁易读。最重要的是,您现在拥有一个向访问者显示有效信息的模板。