基于三级自定义分类及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
相关产品推荐
相关产品推荐

