导读:本期聚焦于小伙伴创作的《WooCommerce产品页如何按分类展示交叉销售并排除当前分类树?》,敬请观看详情。不少店铺在商品详情页做关联推荐时,直接调用系统自带的交叉销售,结果推出来的全是同分类的相似款,转化并不理想。更合理的方式是按产品所属分类去匹配其他分类下的互补商品,同时把当前产品所在的整个分类树都过滤掉,避免自推自。实现上可借助WordPress的WP_Query配合分类ID获取与递归子分类查询,在模板中用钩子替换默认输出。需要注意分类树不仅是直接父级,还包含深层子项,否则排除不彻底。下文给出具体函数与钩子写法。

在 WooCommerce 商品详情页中,系统默认的交叉销售(cross-sells)依赖于后台手动设置,难以根据商品分类自动推荐互补品。更实用的做法是:获取当前产品所属分类,向上向下递归整棵分类树,然后用 WP_Query 查询不属于该分类树的其他分类产品,实现自动化关联展示。

WooCommerce产品页如何按分类展示交叉销售并排除当前分类树?

为什么需要排除当前分类树

很多站点只是排除了产品的直接父分类,但 WooCommerce 商品分类往往是多层结构。例如「服装」下面有「男装」,男装下还有「T恤」。如果当前商品属于「T恤」,仅排除「T恤」或「男装」是不够的,应当把「服装」这一整条祖先链以及其所有分支都视为同一分类树。

若不排除完整分类树,交叉销售区就可能再次出现同系列商品,失去跨品类引流意义。从用户体验看,在买 T 恤时推荐裤子或鞋子,比推荐另一个 T 恤更容易激发加购。因此,代码核心在于「获取分类树全部 ID」。

获取当前产品的完整分类树 ID

我们可以通过 wp_get_post_terms() 拿到直接分类,再用 get_ancestors() 获取祖先,并递归收集子分类。下面函数返回当前商品所属所有相关分类 ID 的数组。

function get_product_category_tree_ids( $product_id ) {
    $terms = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
    if ( is_wp_error( $terms ) || empty( $terms ) ) {
        return array();
    }
    $tree_ids = array();
    foreach ( $terms as $term_id ) {
        // 当前分类
        $tree_ids[] = $term_id;
        // 祖先分类
        $ancestors = get_ancestors( $term_id, 'product_cat' );
        if ( ! empty( $ancestors ) ) {
            $tree_ids = array_merge( $tree_ids, $ancestors );
        }
        // 所有子分类
        $children = get_term_children( $term_id, 'product_cat' );
        if ( ! empty( $children ) && ! is_wp_error( $children ) ) {
            $tree_ids = array_merge( $tree_ids, $children );
        }
    }
    return array_unique( array_map( 'intval', $tree_ids ) );
}

该函数先把直接分类放入数组,再利用 get_ancestors() 把父级、祖父级等全部拉入,最后用 get_term_children() 把下属子分类也合并。使用 array_unique() 防止重复 ID 导致查询异常。

要注意 get_term_children() 返回的是子孙分类的扁平 ID 列表,不会包含自身,所以前面必须手动加入当前 $term_id。这样我们就拥有了一棵完整的分类树。

基于分类树查询交叉销售产品

拿到排除用的分类 ID 后,使用 WP_Query 查询不在该数组中的其他分类商品。下面示例在商品页展示 4 个其他分类产品。

function get_cross_sell_by_category( $product_id, $limit = 4 ) {
    $exclude_tree = get_product_category_tree_ids( $product_id );
    $args = array(
        'post_type'      => 'product',
        'posts_per_page' => $limit,
        'post_status'    => 'publish',
        'post__not_in'   => array( $product_id ),
        'tax_query'      => array(
            array(
                'taxonomy' => 'product_cat',
                'field'    => 'term_id',
                'terms'    => $exclude_tree,
                'operator' => 'NOT IN',
            ),
        ),
        'orderby'        => 'rand',
    );
    $query = new WP_Query( $args );
    return $query->posts;
}

上面的 tax_query 使用 NOT IN 操作符,直接过滤掉整棵分类树。配合 post__not_in 排除自身,避免自己推荐自己。排序用随机,可让不同访客看到不同互补品。

这种写法的优点是逻辑清晰、不依赖手动设置;缺点是随机查询在大数据量时略有性能开销,可通过增加 meta_query 限定有库存商品来优化。

在模板中替换默认交叉销售

WooCommerce 提供了 woocommerce_after_single_product_summary 钩子。我们可以移除默认 cross-sells,再挂载自己的函数。

remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_cross_sell_display', 20 );

add_action( 'woocommerce_after_single_product_summary', 'custom_cross_sell_display', 20 );
function custom_cross_sell_display() {
    global $product;
    if ( ! $product ) {
        return;
    }
    $cross_sells = get_cross_sell_by_category( $product->get_id(), 4 );
    if ( empty( $cross_sells ) ) {
        return;
    }
    echo '<section class="cross-sells">';
    echo '<h2>相关分类推荐</h2>';
    echo '<ul class="products">';
    foreach ( $cross_sells as $p ) {
        $wc_p = wc_get_product( $p->ID );
        echo '<li>' . $wc_p->get_title() . '</li>';
    }
    echo '</ul>';
    echo '</section>';
}

将以上代码放入主题的 functions.php 或自定义插件中即可生效。实际项目中可进一步调用 wc_get_template_part() 复用 WooCommerce 自带卡片样式,保持视觉统一。

如果需要更精细控制,比如只排除祖先而不排除兄弟分类,可调整 get_product_category_tree_ids() 中的子分类收集逻辑。整体方案灵活且易于维护。

常见误区与注意事项

有人会用 wp_get_post_categories() 代替 wp_get_post_terms(),但该产品分类法为 product_cat,并非默认 category,必须用正确的 taxonomy 参数。

另外,缓存查询结果能显著提升性能。可使用 wp_cache_set() 按产品 ID 缓存交叉销售列表,过期时间设为几小时,避免每次页面加载都跑随机查询。

WooCommerce交叉销售分类树排除修改时间:2026-08-07 09:27:15

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。