WP DEVELOP

EP082. “按关联关系搜索:动态化 + 修复正文误命中”

首页 WordPress 开发课程 前端 OVERLAY 串接自定义 API · EP082
约 13 分钟· #EP082#前端 OVERLAY 串接自定义 API
🔒 登录后可标记已读

把上一讲写死 ID 97(biology)的关联查询改成真正动态:先给 Program 结果补上 id 字段,再用 foreach 循环按当前搜到的全部 Program(可能不止一个)动态拼出 meta_query 数组,并用 relation => 'OR' 让「关联到 A 项目或 B 项目」都算命中。中途还发现一个误命中问题——如果 Program 正文里提到了另一个项目名(比如 biology 项目正文里写了 "math"),搜索 math 会连带把 biology 也搜出来,于是新建一个 ACF 字段 main_body_content 专门放正文,让 WordPress 默认搜索不再扫描这个字段,从根源上解决误命中。


涉及文件

  • wp-content/themes/fictional-university-theme/inc/search-route.php (修改)
  • wp-content/themes/fictional-university-theme/single-program.php (修改)
  • wp-content/mu-plugins/university-post-types.php (修改)
  • Program 文章类型新增 ACF 字段组 main_body_content(后台 Custom Fields 界面操作,无对应代码文件)

代码实现

inc/search-route.php:Program 结果补上 id 字段(在原本的主查询 while 循环、program 分支里):

// wp-content/themes/fictional-university-theme/inc/search-route.php
// program 分支新增:
'permalink' => get_the_permalink(),
'id' => get_the_id()

inc/search-route.php:把上一讲写死的关联查询改成动态生成(替换掉 EP081 那段硬编码的 meta_query 数组):

// wp-content/themes/fictional-university-theme/inc/search-route.php

// 只有当关键词搜索确实命中了 Program,才需要去查关联的教授
if ($results['programs']) {
  $programsMetaQuery = array('relation' => 'OR');

  foreach ($results['programs'] as $item) {
    array_push($programsMetaQuery, array(
      'key' => 'related_programs',
      'compare' => 'LIKE',
      'value' => '"' . $item['id'] . '"'
    ));
  }

  $programRelationshipQuery = new WP_Query(array(
    'post_type' => 'professor',
    'meta_query' => $programsMetaQuery
  ));

  while ($programRelationshipQuery->have_posts()) {
    $programRelationshipQuery->the_post();

    if (get_post_type() == 'professor') {
      array_push($results['professors'], array(
        'title' => get_the_title(),
        'permalink' => get_the_permalink(),
        'image' => get_the_post_thumbnail_url(0, 'professorLandscape')
      ));
    }
  }

  $results['professors'] = array_values(array_unique($results['professors'], SORT_REGULAR));
}

single-program.php:正文改用新建的 ACF 字段,而不是默认内容字段

// wp-content/themes/fictional-university-theme/single-program.php
// 修改:
<div class="generic-content"><?php the_field('main_body_content'); ?></div>

mu-plugins/university-post-types.php:Program 文章类型移除默认内容编辑器

// wp-content/mu-plugins/university-post-types.php
// 修改:Program 的 supports 数组去掉 'editor'
'supports' => array('title'),

关键改动点:

  • $programsMetaQuery 先手动放一个 'relation' => 'OR',再用 foreach 遍历 $results['programs'],每个命中的 Program 都 array_push 一条 LIKE '"ID"' 的过滤条件——这样不管关键词搜索命中 1 个还是 10 个 Program,都能生成正确数量的 OR 条件,不用手写固定几条
  • 整段关联查询代码包在 if ($results['programs']) 里:如果关键词搜索没搜到任何 Program,$programsMetaQuery 只剩一个 relation => OR 没有任何实际过滤条件,WordPress 会把它当成「没有过滤条件」处理,等于查出全部教授——所以必须先判断有没有命中 Program 再执行这段查询
  • 误命中问题的根源:WordPress 默认关键词搜索会扫描 post_content(默认内容字段),如果 Program 正文里提到别的项目名,就会被误搜到。解法不是自己写 SQL,而是新建一个 ACF 字段(WYSIWYG 类型,main_body_content,只在 post type = program 时显示,位置设为 high 排在标题下方)专门放正文——WordPress 默认搜索不会去扫描 ACF 字段的内容,问题就消失了
  • 新增 ACF 字段后要同步做两件事:① single-program.php 改用 the_field('main_body_content') 而不是 the_content();② 后台默认的内容编辑器意义已经不大,从 supports 数组里去掉 'editor',避免后台出现两个正文输入框造成混淆

[截图:前台搜索 overlay 输入 math,确认不再误命中正文里提到 math 但实际无关的 biology 项目]


Hook / Function 速查

名称类型用途
get_the_id()WP 内建 function获取当前循环 post 的文章 ID
array_push($arr, $item)PHP 内建 function往数组末尾追加一个元素,这里循环用来动态拼 meta_query 条件
the_field('字段名')ACF function直接输出(echo)一个 ACF 字段的值
register_post_type()supports 参数WP 内建注册参数控制编辑页面显示哪些默认功能区块,去掉 'editor' 就不再显示默认内容编辑器

常见坑

  • 关联查询代码不包 if ($results['programs']) 判断——关键词没搜到任何 Program 时,meta_query 里只剩 relation => OR 一条、没有实际过滤条件,WordPress 会当成「无条件」处理,等于查出全部教授,而不是零个
  • 以为可以直接改 SQL 语句解决正文误命中问题——作者明确不建议手改 WordPress 默认 SQL,用 ACF 字段替换默认内容字段是更安全、更符合 WordPress 习惯的做法
  • 新建 ACF 字段后忘记同步改模板文件——single-program.php 如果还在用 the_content(),前台会显示空白,因为正文已经改存到新字段里了

延伸 / 后续讲座会用到

下一讲(EP083)会用同样的思路,把 Events 和 Campuses 也接入按关联关系搜索,完成整个搜索 Overlay 功能。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 16, EP082