You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress自定义文章类型分类层级展示:父分类去重优化求助

问题解决:WordPress自定义分类层级下文章分组展示(父分类仅显示一次)

核心问题分析

原代码使用拼接后的HTML字符串作为数组$q的键,导致同一父分类下的不同子分类会生成不同的键,最终渲染时父分类重复输出。要实现层级化展示,需要基于分类的term_id构建多维数组,按「父分类→子分类→文章」的层级存储数据,而非用HTML字符串作为分组依据。

改进后的完整代码

1. 数据收集与层级分组

<?php
$query = new WP_Query([
    'post_type'      => 'afdigit',
    'posts_per_page' => -1,
    'orderby'        => 'none',
]);

if ($query->have_posts()) {
    // 初始化层级数组:键为父分类term_id,值包含分类信息、子分类列表
    $taxonomy_groups = [];
    $taxonomy = 'afd-cats';

    while ($query->have_posts()) {
        $query->the_post();
        $post_id = get_the_ID();
        // 获取文章对应的所有分类
        $terms = get_the_terms($post_id, $taxonomy);
        
        if (!$terms || is_wp_error($terms)) continue;

        foreach ($terms as $term) {
            // 获取当前分类的顶级父分类
            $top_term = get_top_term($taxonomy, $post_id);
            $top_term_id = $top_term->term_id;

            // 初始化顶级父分类的数组结构
            if (!isset($taxonomy_groups[$top_term_id])) {
                $taxonomy_groups[$top_term_id] = [
                    'term'        => $top_term,
                    'children'    => [], // 子分类列表:键为子分类term_id
                    'direct_posts' => [] // 直接属于父分类的文章
                ];
            }

            // 判断当前分类是否是顶级父分类本身
            if ($term->term_id === $top_term_id) {
                // 文章直接属于父分类,添加到direct_posts
                $taxonomy_groups[$top_term_id]['direct_posts'][] = [
                    'title' => get_the_title(),
                    'link'  => get_permalink()
                ];
            } else {
                // 文章属于子分类,初始化子分类结构(如果不存在)
                if (!isset($taxonomy_groups[$top_term_id]['children'][$term->term_id])) {
                    $taxonomy_groups[$top_term_id]['children'][$term->term_id] = [
                        'term'  => $term,
                        'posts' => []
                    ];
                }
                // 添加文章到对应子分类
                $taxonomy_groups[$top_term_id]['children'][$term->term_id]['posts'][] = [
                    'title' => get_the_title(),
                    'link'  => get_permalink()
                ];
            }
        }
    }

    wp_reset_postdata();
?>

2. 层级化渲染输出

<div class="cat">
    <?php foreach ($taxonomy_groups as $group) : ?>
        <div class="term">
            <!-- 输出顶级父分类 -->
            <div class="top term_">
                <a href="<?php echo get_term_link($group['term']); ?>">
                    <?php echo esc_html($group['term']->name); ?>
                </a>
            </div>

            <!-- 输出直接属于父分类的文章 -->
            <?php if (!empty($group['direct_posts'])) : ?>
                <ul class="posts">
                    <?php foreach ($group['direct_posts'] as $post) : ?>
                        <li class="post">
                            <a href="<?php echo esc_url($post['link']); ?>">
                                <?php echo esc_html($post['title']); ?>
                            </a>
                        </li>
                    <?php endforeach; ?>
                </ul>
            <?php endif; ?>

            <!-- 输出子分类及其文章 -->
            <?php foreach ($group['children'] as $child) : ?>
                <div class="child">
                    <a href="<?php echo get_term_link($child['term']); ?>">
                        <?php echo esc_html($child['term']->name); ?>
                    </a>
                </div>
                <ul class="posts">
                    <?php foreach ($child['posts'] as $post) : ?>
                        <li class="post">
                            <a href="<?php echo esc_url($post['link']); ?>">
                                <?php echo esc_html($post['title']); ?>
                            </a>
                        </li>
                    <?php endforeach; ?>
                </ul>
            <?php endforeach; ?>
        </div>
    <?php endforeach; ?>
</div>
<?php } ?>

3. 优化get_top_term函数(增强健壮性)

function get_top_term($taxonomy, $post_id = 0)
{
    // 处理post_id参数:支持传入WP_Post对象或ID
    if (is_object($post_id) && isset($post_id->ID)) {
        $post_id = $post_id->ID;
    }
    $post_id = $post_id ?: get_the_ID();

    $terms = get_the_terms($post_id, $taxonomy);
    if (!$terms || is_wp_error($terms)) {
        return false;
    }

    // 取第一个分类(如果文章有多个分类,可根据需求调整)
    $term = reset($terms);
    // 向上遍历直到找到顶级父分类
    while ($term->parent > 0) {
        $parent_term = get_term_by('id', $term->parent, $taxonomy);
        if (!$parent_term || is_wp_error($parent_term)) break;
        $term = $parent_term;
    }

    return $term;
}

关键改进点说明

  • 数据结构重构:用term_id作为数组键,避免HTML字符串导致的重复分组,确保同一父分类下的子分类和文章都归到同一个父分类节点下。
  • 安全输出:使用esc_html()和esc_url()处理输出内容,避免XSS安全风险(原代码未做转义,存在隐患)。
  • 逻辑拆分:将数据收集和渲染分离,代码更易维护和调试。
  • 空值处理:增加对分类不存在或错误的判断,避免页面报错。

最终输出效果

Category 1
    Post
    Post
    Post

Category 2
    Post
    Post
    Post

Parent category 1
  Child category 1
    Post
    Post
    Post

  Child category 2
    Post
    Post
    Post

Category 3
    Post
    Post
    Post

内容的提问来源于stack exchange,提问作者Sergey Pervushin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:15:39