WooCommerce新建产品前校验SKU并自动处理重复值求助
WooCommerce 自动生成唯一SKU并避免重复报错的解决方案
需求:在WooCommerce中保存新建产品前校验SKU,避免因SKU重复引发报错,自动将重复SKU调整为唯一值。现有代码无法生效,无论SKU是否重复产品都会直接保存。
现有代码的问题分析
- 钩子参数顺序错误:
woocommerce_before_product_object_save的参数顺序是$product在前,$product_id在后,原代码写反导致后续逻辑无法正确获取产品数据和ID。 - 过滤器与校验逻辑冲突:通过
wc_product_has_unique_sku过滤器返回false禁用了默认校验,但后续又调用wc_product_has_unique_sku()判断重复,这个函数会被过滤器影响,导致永远返回true,无法触发重复处理逻辑。 - 函数嵌套不规范:在
set_sku内部嵌套generateRandomString函数,虽不报错但不符合代码规范,可能引发上下文问题。
修正后的代码
// 生成随机字符串的工具函数 function generateRandomString($length = 10) { $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return substr(str_shuffle(str_repeat($chars, ceil($length / strlen($chars)))), 0, $length); } // 禁用默认的SKU重复报错(但保留校验能力) add_filter('wc_product_has_unique_sku', function($unique, $product_id, $sku) { // 自定义处理重复逻辑,不让默认校验抛出错误 return true; }, 10, 3); // 在产品保存前处理SKU唯一性 add_action('woocommerce_before_product_object_save', 'set_unique_sku', 10, 2); function set_unique_sku($product, $product_id) { $current_sku = $product->get_sku(); // 如果SKU为空,用产品slug填充 if (empty($current_sku)) { $product->set_sku($product->get_slug()); $current_sku = $product->get_sku(); } // 手动校验SKU是否重复(直接查询数据库,不受过滤器影响) $existing_product_id = wc_get_product_id_by_sku($current_sku); // 排除当前产品(编辑场景下不判定自身为重复) if ($existing_product_id && $existing_product_id != $product_id) { // 循环生成直到得到唯一SKU do { $new_sku = $current_sku . '-' . generateRandomString(); $check_id = wc_get_product_id_by_sku($new_sku); } while ($check_id); $product->set_sku($new_sku); } }
关键修改说明
- 修正钩子参数顺序,确保正确获取产品对象和ID;
- 改用
wc_get_product_id_by_sku()直接查询数据库,避免过滤器干扰重复判断; - 增加循环校验,确保生成的带随机后缀的SKU也不会重复;
- 处理编辑场景,排除当前产品ID,避免误判;
- 规范函数结构,将随机字符串生成函数独立出来。
内容的提问来源于stack exchange,提问作者Jonas Borneland
相关产品推荐
相关产品推荐

