如何为WooCommerce优惠券排除分类下拉列表添加父分类名称?
问题背景
运营WooCommerce服装商店时,优惠券「使用限制」中的「排除分类」下拉选项会将多级分类结构扁平化,导致无法区分同名称的子分类(比如Men下的Jeans和Women下的Jeans)。期望下拉列表显示带父分类前缀的层级结构,例如Men » Jeans。
当前分类结构:
- Men
- Shirts
- Jeans
- Sale
- Women
- Shirts
- Jeans
- Sale
现有下拉显示(扁平化):
- Jeans
- Men
- Sale
- Sale
- Shirts
- Shirts
- Women
解决方案
方法1:利用WordPress全局get_terms过滤器(推荐)
虽然WooCommerce优惠券元框代码未单独添加过滤器,但WordPress核心的get_terms函数自带全局过滤器,可通过该过滤器限定仅在优惠券编辑页面修改分类名称显示,避免影响全局功能。
代码示例:
if (!function_exists('wc_coupon_category_add_parent_prefix')) { function wc_coupon_category_add_parent_prefix($terms, $taxonomies, $args) { // 仅在优惠券编辑页面的产品分类查询中生效 if (!is_admin() || !isset($_GET['post_type']) || $_GET['post_type'] !== 'shop_coupon' || !in_array('product_cat', $taxonomies)) { return $terms; } foreach ($terms as &$term) { if ($term->parent > 0) { $parent_term = get_term($term->parent, 'product_cat'); if (!is_wp_error($parent_term)) { $term->name = $parent_term->name . ' » ' . $term->name; } } } return $terms; } add_filter('get_terms', 'wc_coupon_category_add_parent_prefix', 10, 3); }
将代码添加到主题的functions.php文件或自定义插件中即可生效,该代码仅针对优惠券编辑页面的分类下拉添加父分类前缀,不影响其他场景的分类显示。
方法2:直接修改WooCommerce核心文件(不推荐,易被更新覆盖)
若不想使用过滤器,可直接修改WooCommerce的优惠券元框文件,但需注意:WooCommerce更新后会覆盖修改内容,每次版本更新需重新操作。
找到文件wp-content/plugins/woocommerce/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php,定位到$categories = get_terms('product_cat', 'orderby=name&hide_empty=0');这一行,替换为以下代码:
$categories = get_terms('product_cat', 'orderby=name&hide_empty=0'); // 为子分类添加父分类前缀 foreach ($categories as &$category) { if ($category->parent > 0) { $parent = get_term($category->parent, 'product_cat'); if (!is_wp_error($parent)) { $category->name = $parent->name . ' » ' . $category->name; } } }
方法3:前端JavaScript修改(无需后端代码侵入)
若不想修改PHP代码,可通过JavaScript在页面加载后动态修改下拉选项文本:
1. 添加前端JS代码
将以下代码添加到主题的自定义JS文件或后台自定义脚本中:
jQuery(document).ready(function($) { // 仅在优惠券编辑页面执行 if ($('body').hasClass('post-type-shop_coupon')) { // 定位排除分类下拉框 var $excludeCatSelect = $('select#exclude_product_categories'); if ($excludeCatSelect.length) { $excludeCatSelect.find('option').each(function() { var termId = $(this).val(); if (termId) { // 通过AJAX获取分类的父分类信息 $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'get_product_cat_parent', term_id: termId }, success: function(response) { if (response.parent_name) { $(this).text(response.parent_name + ' » ' + $(this).text()); } }.bind(this) }); } }); } } });
2. 添加后端AJAX处理函数
将以下代码添加到主题functions.php或自定义插件中:
add_action('wp_ajax_get_product_cat_parent', 'get_product_cat_parent_callback'); function get_product_cat_parent_callback() { $term_id = isset($_POST['term_id']) ? intval($_POST['term_id']) : 0; $term = get_term($term_id, 'product_cat'); if (!is_wp_error($term) && $term->parent > 0) { $parent = get_term($term->parent, 'product_cat'); if (!is_wp_error($parent)) { wp_send_json(array('parent_name' => $parent->name)); } } wp_send_json(array('parent_name' => '')); }
内容的提问来源于stack exchange,提问作者Ronaldt

