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

基于三级自定义分类及RankMath主术语优化WooCommerce关联商品

WooCommerce关联商品按RankMath主术语及分类层级优先匹配的代码修改

问题说明

我有一个带自定义分类sport的WooCommerce商店,该分类分三级:父级>子级>孙级(比如Indoor Sport > Arena Sport > Basketball)。浏览篮球商品时,希望关联商品优先展示同孙级(Basketball)的商品,数量不足时再降级显示子级(Arena Sport)的商品,以此类推。

同时我用RankMath插件设置了「主术语」(Primary),通常是孙级,偶尔也会是子级。当前代码仅能匹配子级分类商品,无法优先展示主术语对应的孙级商品,需要修改代码实现按优先级匹配的逻辑。

现有代码

add_filter( 'woocommerce_related_products', 'related_products_from_rankmath_primary_esporte_taxonomy', 10, 3 );
function related_products_from_rankmath_primary_esporte_taxonomy( $related_posts, $product_id, $args ) {
    $taxonomy     = 'sport'; 
    $term_ids     = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) ); 
    $term_slugs   = array(); 

 if( count($term_ids) == 1 ) {
        // Get children categories
        $children_ids = get_term_children( reset($category_ids), $taxonomy );
        // Loop through children terms Ids
        foreach ( $children_ids as $tem_id ) {
            $term_slugs[] = get_term_by( 'id', $tem_id, $taxonomy )->slug; // get the slug from each term Id
        }
    } 
    elseif( count( $term_ids ) > 1 ) {
        // Get the primary taxonomy/term as saved by Rank Math SEO
        $primary_tax_id = get_post_meta( $product_id, 'rank_math_primary_taxonomy', true );
        $term_slugs[]   = get_term_by( 'id', $primary_tax_id, $taxonomy )->slug; // get the slug from the term Id
    }
        
        
    if ( count( $term_ids ) > 0 ) {
        foreach ( $term_ids as $term_id ) {
            $term_slugs[] = get_term_by( 'id', $term_id, $taxonomy )->slug; 

            // Gets the IDs of child terms
            $children_ids = get_term_children( $term_id, $taxonomy );

            foreach ( $children_ids as $child_id ) {
                $term_slugs[] = get_term_by( 'id', $child_id, $taxonomy )->slug; // Gets the slug of each child term
            }
        }

        $related_posts = wc_get_products( array(
            'status'        => 'publish',
            'tax_query'     => array(
                array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'slug',
                    'terms'    => $term_slugs,
                ),
            ),
            'return'        => 'ids',
            'exclude'       => array( $product_id ),
            'visibility'    => 'catalog',
            'limit'         => -1,
        ) );
    }

    return $related_posts;
}

修改方案

核心逻辑是按优先级顺序查询商品:先收集主术语下的商品,数量不够则向上取父级术语的商品补充,直到达到默认的关联商品数量。具体修改如下:

修改后的代码

add_filter( 'woocommerce_related_products', 'related_products_from_rankmath_primary_sport_taxonomy', 10, 3 );
function related_products_from_rankmath_primary_sport_taxonomy( $related_posts, $product_id, $args ) {
    $taxonomy = 'sport';
    $default_limit = $args['posts_per_page']; // 获取默认关联商品数量
    $related_ids = array();

    // 1. 获取主术语ID(优先RankMath设置的主术语)
    $primary_tax_id = get_post_meta( $product_id, 'rank_math_primary_taxonomy', true );
    if ( empty( $primary_tax_id ) ) {
        $term_ids = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) );
        $primary_tax_id = reset( $term_ids ); // 没有主术语则取第一个分类ID
    }

    if ( empty( $primary_tax_id ) ) {
        return $related_posts; // 无分类则返回原关联商品
    }

    // 2. 构建优先级术语链:主术语 → 父级术语 → 顶级父级
    $term_chain = array();
    $current_term = get_term( $primary_tax_id, $taxonomy );
    
    while ( ! is_wp_error( $current_term ) && $current_term ) {
        $term_chain[] = $current_term->slug;
        $current_term = get_term( $current_term->parent, $taxonomy ); // 向上遍历父级
    }

    // 3. 按优先级查询商品,先取主术语的,数量不够再补父级的
    foreach ( $term_chain as $term_slug ) {
        if ( count( $related_ids ) >= $default_limit ) {
            break; // 数量够了就停止
        }

        $remaining = $default_limit - count( $related_ids );
        $products = wc_get_products( array(
            'status'        => 'publish',
            'tax_query'     => array(
                array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'slug',
                    'terms'    => $term_slug,
                    'operator' => 'IN'
                ),
            ),
            'return'        => 'ids',
            'exclude'       => array_merge( array( $product_id ), $related_ids ), // 排除当前商品和已选商品
            'visibility'    => 'catalog',
            'limit'         => $remaining,
        ) );

        $related_ids = array_merge( $related_ids, $products );
    }

    // 4. 返回最终的关联商品ID数组
    return $related_ids;
}

关键修改点说明

  • 优先级术语链:从主术语开始向上遍历所有父级,形成明确的优先级顺序(孙级→子级→父级)
  • 分步查询:按术语优先级依次查询商品,每次只补够剩余需要的数量,保证高优先级商品先展示
  • 排除已选商品:每次查询时排除已经选中的商品,避免重复
  • 适配默认数量:使用WooCommerce默认的关联商品数量$args['posts_per_page'],无需硬编码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:29:53