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

WordPress自定义分类:指定分类术语始终显示在末尾的实现问题

问题:自定义分类按文章数排序并将特定分类固定在末尾

我已创建名为Jobs的自定义文章类型,关联work-category自定义分类,当前使用以下代码可按分类下文章数量降序展示分类及对应文章(代码正常运行):

<div class="col-lg-10">
    <?php
    $terms = get_terms([
    'taxonomy' => 'work-category',
    'hide_empty' => true,
    'orderby'  => 'count',
    'order' => 'DESC',
    ]);


    if ($terms) {
    foreach ($terms as $category) { ?>

        <h2 class="category-h2">
            <?= $category->name ?>
        </h2>


        <?php
        $posts = get_posts(array(
            'posts_per_page'    => -1,
            'post_type'         => 'jobs',
            'tax_query' => [
            [
                'taxonomy' => 'work-category',
                'field' => 'term_id',
                'terms' => $category->term_id,
            ]
            ]
        ));

        if ( $posts ) {
            foreach( $posts as $post ) {
            setup_postdata( $post );
            include 'WorkView.php';
            };
            wp_reset_postdata();
        }

    }
    } else { //no categories

    $posts = get_posts(array(
        'posts_per_page'    => -1,
        'post_type'         => 'career'
    ));

    if ( $posts ) {
        foreach( $posts as $post ) {
        setup_postdata( $post );
        include 'JobListThumb.php';
        };
        wp_reset_postdata();
    }

    }
    ?>

</div>

新增需求:给work-category分类添加了名为stick_to_end的自定义字段,要求所有分类按文章数量降序排列,但标记该字段的分类始终显示在末尾。我尝试了两种方法均无效:

  • 在orderby中使用数组:'orderby' => array ('count' => DESC, 'stick_to_end' => ASC)
  • 使用meta_query:
'meta_query' => array(
            'relation' => 'AND',
            array(
                'key'      => 'count',
                'value'    => EXISTS, 
            ),
            array(
                'key'      => 'stick_to_end',
                'compare'  => '=',
                'value'    => false, 
            ),
        )

问题分析

你之前的方法无效的原因:

  1. get_terms的orderby参数默认不支持直接将自定义元字段与分类自带的count字段组合排序,因为默认查询不会加载分类元数据,所以数组排序规则无法生效。
  2. 第二种方法中的meta_query逻辑错误:count是分类自带的文章数字段,不是自定义元字段,且该查询是筛选分类而非排序,只会过滤掉stick_to_end为true的分类,无法实现将它们放在末尾的效果。

解决方案

方案一:PHP层面手动拆分排序(简单直观)

先获取所有分类,再按stick_to_end字段拆分两组,最后合并正常组在前、末尾组在后:

<div class="col-lg-10">
    <?php
    // 获取所有work-category分类,包含元数据查询
    $terms = get_terms([
        'taxonomy' => 'work-category',
        'hide_empty' => true,
        'orderby' => 'count',
        'order' => 'DESC',
        // 确保查询包含有stick_to_end字段和没有该字段的分类
        'meta_query' => [
            'relation' => 'OR',
            ['key' => 'stick_to_end', 'compare' => 'EXISTS'],
            ['key' => 'stick_to_end', 'compare' => 'NOT EXISTS']
        ]
    ]);

    // 拆分分类为两组
    $normal_terms = [];
    $sticky_end_terms = [];
    foreach ($terms as $term) {
        // 获取自定义字段值,默认返回false
        $stick_to_end = get_term_meta($term->term_id, 'stick_to_end', true);
        if ($stick_to_end) {
            $sticky_end_terms[] = $term;
        } else {
            $normal_terms[] = $term;
        }
    }

    // 合并两组:正常分类在前,需要固定在末尾的分类在后
    $sorted_terms = array_merge($normal_terms, $sticky_end_terms);

    if ($sorted_terms) {
        foreach ($sorted_terms as $category) { ?>

            <h2 class="category-h2">
                <?= $category->name ?>
            </h2>

            <?php
            $posts = get_posts(array(
                'posts_per_page'    => -1,
                'post_type'         => 'jobs',
                'tax_query' => [
                    [
                        'taxonomy' => 'work-category',
                        'field' => 'term_id',
                        'terms' => $category->term_id,
                    ]
                ]
            ));

            if ( $posts ) {
                foreach( $posts as $post ) {
                    setup_postdata( $post );
                    include 'WorkView.php';
                };
                wp_reset_postdata();
            }

        }
    } else { //no categories

        $posts = get_posts(array(
            'posts_per_page'    => -1,
            'post_type'         => 'career'
        ));

        if ( $posts ) {
            foreach( $posts as $post ) {
                setup_postdata( $post );
                include 'JobListThumb.php';
            };
            wp_reset_postdata();
        }

    }
    ?>

</div>

方案二:数据库层面修改排序(性能更优)

通过terms_clauses过滤器修改SQL查询,直接在数据库层面实现先按stick_to_end分组排序,再按文章数降序:

在主题的functions.php中添加以下代码:

add_filter('terms_clauses', function($clauses, $taxonomy, $args) {
    // 仅针对work-category分类,且按count排序时生效
    if ($taxonomy !== 'work-category' || ($args['orderby'] ?? '') !== 'count') {
        return $clauses;
    }

    global $wpdb;
    // 关联termmeta表,查询stick_to_end字段
    $clauses['join'] .= " LEFT JOIN {$wpdb->termmeta} tm ON t.term_id = tm.term_id AND tm.meta_key = 'stick_to_end'";
    // 修改排序规则:先将stick_to_end为true的分类放到后面,再按count降序
    $clauses['orderby'] = "CASE WHEN tm.meta_value = '1' THEN 1 ELSE 0 END ASC, {$clauses['orderby']}";

    return $clauses;
}, 10, 3);

添加后,你原来的get_terms代码无需修改,查询出的分类会自动将标记stick_to_end的分类放在末尾,其他分类仍按文章数降序排列。


方案对比

  • 方案一:无需修改全局代码,逻辑简单易懂,适合分类数量较少的场景。
  • 方案二:直接在数据库层面处理,性能更优,适合分类数量较多的场景,但需要添加全局过滤器,注意限定生效范围。

内容的提问来源于stack exchange,提问作者Julia Galden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:45:38