
本文介绍如何通过追踪文章浏览量,从热门文章中提取其所属的自定义分类法(如 seasons),并确保每个分类项仅显示一次,避免重复输出,同时支持获取 id、名称、链接等完整信息。
本文介绍如何通过追踪文章浏览量,从热门文章中提取其所属的自定义分类法(如 seasons),并确保每个分类项仅显示一次,避免重复输出,同时支持获取 id、名称、链接等完整信息。
在 WordPress 开发中,若需在首页或侧边栏展示“最受欢迎的分类/标签/自定义分类法”,常需借助文章浏览统计间接实现——因为 WordPress 原生不记录分类法访问量。典型做法是:先统计单篇文章浏览数(通过 post_meta 存储),再按浏览量排序获取热门文章,最后从中提取其关联的自定义分类法(如 seasons),并去重汇总。
但直接在循环内逐个输出分类项会导致严重重复:例如 5 篇热门视频都属于同一季(seasons 分类下的 “S01”),该分类就会被渲染 5 次。原方案尝试用 array_unique() 处理字符串 ID,却因误在每次循环中重建数组而失效。
✅ 正确解法是:提前声明一个空数组用于全局收集唯一 term ID,在整个 WP_Query 循环结束后统一处理或即时去重输出。以下是优化后的完整实现:
<?php
// 1. 构建热门文章查询(注意:此处暂不按浏览量排序,因需兼容 get_the_terms 的上下文)
$popular = array(
'post_type' => 'videos',
'posts_per_page' => 8,
'meta_key' => 'post_views_count',
'orderby' => 'meta_value_num',
'order' => 'DESC', // 改为 DESC 获取真正「最热」
'post_status' => 'publish'
);
$popular_loop = new WP_Query($popular);
if ($popular_loop->have_posts()) {
$unique_terms = []; // ✅ 全局唯一 term_id 容器
while ($popular_loop->have_posts()) : $popular_loop->the_post();
// 获取当前文章在 'seasons' 分类法下的所有术语
$terms = get_the_terms(get_the_ID(), 'seasons');
if (!is_array($terms) || is_wp_error($terms)) {
continue; // 跳过无分类或出错的文章
}
foreach ($terms as $term) {
// ✅ 仅当该 term_id 尚未加入数组时才添加并输出
if (!in_array($term->term_id, $unique_terms)) {
$unique_terms[] = $term->term_id;
// 输出基础信息(可扩展为完整卡片)
echo '<div class="season-item">';
echo '<h4><a href="' . esc_url(get_term_link($term)) . '">' . esc_html($term->name) . '</a></h4>';
echo '<p>ID: ' . absint($term->term_id) . '</p>';
// 如需输出分类法图片(需配合 Advanced Custom Fields 或 taxonomy image 插件)
// $thumbnail_id = get_term_meta($term->term_id, 'season_thumbnail_id', true);
// if ($thumbnail_id) {
// echo wp_get_attachment_image($thumbnail_id, 'thumbnail');
// }
echo '</div>';
}
}
endwhile;
wp_reset_postdata(); // ✅ 务必重置全局 $post 对象
} else {
echo '<p>暂无热门视频。</p>';
}
?>? 关键要点说明:
- in_array($term->term_id, $unique_terms) 是去重核心逻辑,比 array_unique() 更可控且无需额外合并;
- 使用 get_the_ID() 替代 $post->ID 更安全(避免全局变量污染);
- 排序应设为 'order' => 'DESC' 才能获取浏览量最高的文章(原文误写为 ASC);
- 添加 post_status => 'publish' 避免草稿干扰;
- get_term_link($term) 提供标准分类页链接,务必 esc_url() 过滤;
- 所有用户输出内容(如 $term->name)必须 esc_html() 转义,防止 XSS;
- 若需按热度加权展示(如某分类出现频次越高越靠前),可改用 array_count_values() 统计后排序。
? 进阶建议:
- 将此逻辑封装为短代码或自定义 Widget,提升复用性;
- 结合 Transients API 缓存结果(如 set_transient('popular_seasons', $output, DAY_IN_SECONDS)),减轻数据库压力;
- 若分类层级复杂(含父子关系),可通过 $term->parent 判断并只取顶级分类,避免子分类冗余。
通过以上结构化实现,即可稳定、安全、高性能地展示去重后的热门自定义分类法列表。


















