EP083. “按关联关系搜索:完成 Events 与 Campuses,搜索 Overlay 收尾”
🔒 登录后可标记已读这一讲把「按关联关系搜索」补完剩下两种内容类型,整个搜索 Overlay 功能到此完工:
- Events:跟 Professor 关联方向一样(Event → 关联到 Program),所以直接把上一讲那个查询的
post_type从只查professor扩展成同时查array('professor', 'event'),几乎是顺手就做完的 - Campuses:关联方向是反过来的(Program 关联到 Campus,不是 Campus 关联到 Program),所以不需要新建查询,直接在主查询循环到 Program 时,用
get_field()读出它关联的 Campus 顺手 push 进结果就行
涉及文件
wp-content/themes/fictional-university-theme/inc/search-route.php(修改)
代码实现
扩展关联查询同时覆盖 Professor 和 Event(post_type 从字符串改成数组,while 循环里新增 event 分支,并复用 EP079 写好的 month/day/description 计算逻辑):
// wp-content/themes/fictional-university-theme/inc/search-route.php
$programRelationshipQuery = new WP_Query(array(
'post_type' => array('professor', 'event'), // 修改:从 'professor' 扩展成数组
'meta_query' => $programsMetaQuery
));
while ($programRelationshipQuery->have_posts()) {
$programRelationshipQuery->the_post();
// 新增:event 分支,逻辑跟主查询里的 event 分支一致
if (get_post_type() == 'event') {
$eventDate = new DateTime(get_field('event_date'));
$description = null;
if (has_excerpt()) {
$description = get_the_excerpt();
} else {
$description = wp_trim_words(get_the_content(), 18);
}
array_push($results['events'], array(
'title' => get_the_title(),
'permalink' => get_the_permalink(),
'month' => $eventDate->format('M'),
'day' => $eventDate->format('d'),
'description' => $description
));
}
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));
// 新增:events 也要去重
$results['events'] = array_values(array_unique($results['events'], SORT_REGULAR));
Campus:在主查询循环到 Program 分支时,顺手读出关联的 Campus(关联字段 related_campus 虽然命名是单数,实际存的是数组):
// wp-content/themes/fictional-university-theme/inc/search-route.php
// 在主查询 while 循环、program 分支内新增:
$relatedCampuses = get_field('related_campus');
if ($relatedCampuses) {
foreach ($relatedCampuses as $campus) {
array_push($results['campuses'], array(
'title' => get_the_title($campus),
'permalink' => get_the_permalink($campus)
));
}
}
关键改动点:
- Event 之所以能直接扩展现有的关联查询,是因为它和 Professor 一样,关联方向都是「自己身上有个字段指向 Program」,所以同一个
meta_query(按related_programs关联字段过滤)对两种文章类型都成立,只要把post_type从字符串换成数组即可 - Campus 的关联方向相反:不是 Campus 指向 Program,而是 Program 指向 Campus(作者解释这是因为项目可能有几十上百个,但校区通常只有几个,反过来存更好维护)。既然当前循环到的就是命中的 Program 本身,直接
get_field('related_campus')就能拿到它关联的校区,不需要额外发起一次WP_Query get_the_title($campus)/get_the_permalink($campus)要显式传入$campus(关联字段返回的是校区的文章对象),因为当前循环上下文里 WordPress 认为「当前文章」是这个 Program,不传参数的话拿到的会是 Program 自己的标题和链接,而不是校区的- Campus 的
foreach外面包了一层if ($relatedCampuses),因为related_campus字段允许留空,没有关联校区时get_field()会返回空值/false,直接foreach会报错
[截图:前台搜索 overlay 完整效果,General Information / Programs / Professors / Campuses / Events 五个分组都通过关联关系正确显示结果]
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
get_the_title($post) / get_the_permalink($post) | WP 内建 function | 显式传入文章对象/ID,获取指定文章(而非当前循环文章)的标题/链接 |
常见坑
- Campus 关联字段
related_campus命名是单数,但实际存的是数组(可以关联多个校区)——遍历前要留意这一点,直接当成单个值用会出错 get_the_title()/get_the_permalink()不传参数——在 Program 的循环上下文里调用这两个函数不传$campus参数,拿到的会是 Program 自己的标题和链接,不是校区的,很容易忽略这个细节- Events 关联查询新增后忘记同步补上
array_unique去重——跟 Professors 一样,Event 也可能同时被关键词查询和关联查询命中,产生重复
延伸 / 后续讲座会用到
到这一讲,搜索 Overlay 功能全部完工。下一讲(EP084)会提供一个可选的 jQuery-free 版本 Search.js,用原生 JS + Axios 重写同样的功能,纯属技术选型的补充说明。再往后课程会转向用户权限与角色系统。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 16, EP083