产品、案例、新闻和应用可以通过共享标签建立自动关联;对少数特殊内容,再用 ACF Relationship 字段人工指定。这里的关键是先定义优先级,而不是把两个条件混在一个难以理解的查询里。

让自定义文章类型支持标签
内置 post_tag 默认用于文章。可在注册文章类型时声明,或显式关联:
<?php
add_action(
'init',
function (): void {
register_taxonomy_for_object_type(
'post_tag',
'application'
);
register_taxonomy_for_object_type(
'post_tag',
'case_study'
);
}
);
注册顺序要确保文章类型和 taxonomy 已经存在。更复杂的跨内容关联也可以单独注册一个站点专用 taxonomy,避免把普通博客标签和产品关系混在一起。
读取人工指定内容
建议把 ACF Relationship 字段 related_applications 设置为返回文章 ID。ID 比完整 WP_Post 数组更轻,也更容易与自动结果合并。
<?php
$current_id = get_the_ID();
$manual_ids = get_field(
'related_applications',
$current_id,
false
);
$manual_ids = array_values(
array_unique(
array_filter(
array_map( 'absint', (array) $manual_ids )
)
)
);
$limit = 5;
$ids = array();
if ( $manual_ids ) {
$ids = get_posts(
array(
'post_type' => 'application',
'post_status' => 'publish',
'post__in' => $manual_ids,
'orderby' => 'post__in',
'posts_per_page' => $limit,
'fields' => 'ids',
)
);
}
这里采用“人工指定优先,标签结果补足”的策略,而不是人工字段非空就完全放弃自动推荐。
查询同标签内容
<?php
$tag_ids = wp_get_post_terms(
$current_id,
'post_tag',
array( 'fields' => 'ids' )
);
if ( is_wp_error( $tag_ids ) ) {
$tag_ids = array();
}
if ( count( $ids ) < $limit && $tag_ids ) {
$automatic = new WP_Query(
array(
'post_type' => 'application',
'post_status' => 'publish',
'posts_per_page' => $limit - count( $ids ),
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'post__not_in' => array_merge(
array( $current_id ),
$ids
),
'tag__in' => $tag_ids,
)
);
$ids = array_merge(
$ids,
wp_list_pluck(
$automatic->posts,
'ID'
)
);
}
若使用自定义 taxonomy,把 tag__in 换成明确的 tax_query。不要把 slug 字符串直接拼进 SQL。
按最终顺序渲染
<?php
if ( $ids ) {
$related = new WP_Query(
array(
'post_type' => 'application',
'post_status' => 'publish',
'post__in' => $ids,
'orderby' => 'post__in',
'posts_per_page' => count( $ids ),
'no_found_rows' => true,
)
);
if ( $related->have_posts() ) {
echo '<section aria-labelledby="related-title">';
echo '<h2 id="related-title">相关应用</h2>';
while ( $related->have_posts() ) {
$related->the_post();
get_template_part(
'template-parts/content',
'application-card'
);
}
echo '</section>';
}
wp_reset_postdata();
}
模板片段中的链接、标题和图片应分别使用 esc_url()、esc_html() 与 wp_get_attachment_image()。不要直接信任 ACF 返回的任意 URL 或数组下标。
需要提前约定
- 多个标签是“命中任意一个”还是“必须全部命中”。
- 自动结果按日期、人工排序还是相关度排序。
- 人工指定内容下线后如何补位。
- 不同语言内容能否互相关联。
- 是否允许关联回当前文章,或形成循环推荐。
- 结果是否缓存,以及更新标签时如何失效。
ACF 参考:Relationship 字段。WordPress 参考:register_taxonomy_for_object_type()。