WooCommerce使用get_the_terms获取产品分类及子分类排序异常问题
排序偏差的核心原因
get_the_terms()用于获取当前文章/产品关联的指定分类,这个函数没有内置父-子层级排序逻辑,返回数组的元素排列顺序,完全取决于「分类和当前产品建立关联的时间先后」,和分类本身的层级结构、ID大小没有绑定关系。- 你遇到的CAT_C、CAT_A、CAT_B乱序,本质是编辑产品时,选分类的操作顺序是先勾选最末端的CAT_C,再依次勾选中间层CAT_B、顶层CAT_A,导致原始返回的数组顺序完全匹配勾选操作的先后,根本不满足从父到子的层级输出预期。
- 基于这种不固定顺序的数组使用固定下标取值(比如
$terms[1]->name、$terms[2]->name)的逻辑完全不可靠,只要换个关联分类的操作顺序、甚至重新保存一次产品,取到的分类内容就会错位。 - 注意:即便给
get_the_terms加上排序参数也解决不了问题,因为这个函数的内置排序能力仅支持按名称、ID、分类文章数等维度排序,无法自动梳理分类间的父-子依赖关系。
可落地的层级排序实现
要实现从根分类到末端子分类的顺序输出,需要在拿到原始关联分类数组后,通过递归逻辑重新梳理分类的层级关系,再对排序后的数组做遍历输出。
优化后的完整代码如下:
add_action('woocommerce_single_product_summary' , 'cat_type_before_title', 3); function cat_type_before_title() { $product_id = get_the_ID(); // 获取当前产品关联的所有商品分类 $terms = get_the_terms( $product_id, 'product_cat' ); // 异常兜底:无关联分类时直接返回,避免PHP报错 if ( is_wp_error( $terms ) || empty( $terms ) ) { return; } // 初始化排序后的数组,按层级重新整理 $sorted_terms = []; sort_product_cat_by_hierarchy( $terms, 0, $sorted_terms ); // 遍历排序后的数组输出分类链接 foreach ( $sorted_terms as $term ) { $term_link = get_term_link( $term->term_id ); echo '<a class="single-product-cat-link" href="'. esc_url( $term_link ) . '">'. esc_html( $term->name ) . '</a>'; } } /** * 递归将分类按「父级→子级」的顺序整理到目标数组 * @param array $all_terms 当前产品关联的全部分类 * @param int $parent_id 当前匹配的父级分类ID(0代表顶级分类) * @param array $sorted 排序后的结果数组(引用传递,直接修改原数组) */ function sort_product_cat_by_hierarchy( $all_terms, $parent_id, &$sorted ) { foreach ( $all_terms as $term ) { // 匹配当前父级下的分类,优先存入结果数组 if ( (int)$term->parent === (int)$parent_id ) { $sorted[] = $term; // 递归查找当前分类的所有子分类,继续按层级存入 sort_product_cat_by_hierarchy( $all_terms, $term->term_id, $sorted ); } } }
方案效果说明
- 排序逻辑和分类勾选的先后顺序完全解耦:只要产品关联了CAT_A、CAT_B、CAT_C三个层级的分类,最终输出顺序一定是CAT_A → CAT_B → CAT_C,不会再出现乱序。
- 不需要再依赖固定数组下标取值,直接遍历排序后的数组即可拿到稳定的层级路径。
- 代码里新增了基础的安全转义处理(
esc_url、esc_html),避免分类名称带特殊字符时出现的渲染异常或安全问题。 - 原代码里用
<h2>包裹分类的写法建议调整:分类属于辅助导航信息,不建议使用h2级标题标签,避免和产品主标题、板块标题的层级冲突,影响站点SEO结构。 - 如果产品同时关联了多个独立的分类分支(比如同时关联了CAT_A分支和CAT_D分支),排序后的输出会先完整展示CAT_A从顶级到最末级的路径,再展示CAT_D的全路径,符合常规电商站点的面包屑导航展示逻辑。
内容的提问来源于stack exchange,提问作者Filippo Bertola
相关产品推荐
相关产品推荐

