EP082. “按关联关系搜索:动态化 + 修复正文误命中”
🔒 登录后可标记已读把上一讲写死 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