WooCommerce全变体库存为0时编程复制产品的功能问题求助
WooCommerce 可变产品全变体售罄自动重置方案代码修复
问题根因
现有代码无法完成后续操作的核心原因有两个:
WC_Admin_Duplicate_Product是WooCommerce后台专属类,前台触发woocommerce_thankyou订单完成钩子时默认不会加载,导致产品复制操作看似正常,实际返回的产品对象异常,无法读取新产品ID及关联数据- 调用
get_children()获取变体ID、直接用wp_update_post修改产品属性的操作不符合WooCommerce原生CRUD规范,容易出现缓存未更新、数据写入失败的问题
优化修改点
- 提前加载复制产品所需的后台类,确保前台触发逻辑时类可用
- 改用WooCommerce原生方法读取、修改产品属性,避免直接操作数据库表
- 售罄判断逻辑改用
get_variations()读取所有变体,避免get_available_variations()过滤零库存变体导致判断错误 - 直接继承原产品标题,无需再处理复制后缀,容错率更高
修复后完整代码
function order_checker($order_id) { // 提前加载复制产品所需的后台类,前台触发时默认不加载 if (!class_exists('WC_Admin_Duplicate_Product')) { require_once WC()->plugin_path() . '/includes/admin/class-wc-admin-duplicate-product.php'; } // 获取订单对象 $order = new WC_Order($order_id); // 获取订单内商品 $all_products = $order->get_items(); foreach ($all_products as $product) { $product_object = wc_get_product($product['product_id']); // 仅处理可变产品 if (!$product_object->is_type('variable')) { continue; } $soldout = true; // 遍历所有变体判断是否全部售罄 foreach ($product_object->get_variations() as $variation) { if ($variation->is_in_stock()) { $soldout = false; break; } } if ($soldout) { // 原产品设为草稿 wp_update_post(array( 'ID' => $product['product_id'], 'post_status' => 'draft' )); // 复制生成新产品 $duplicate_product = new WC_Admin_Duplicate_Product(); $new_product = $duplicate_product->product_duplicate($product_object); // 直接设置新产品标题为原产品标题,无需处理复制后缀 $new_product->set_name($product_object->get_name()); // 遍历新产品所有变体设置库存1 foreach ($new_product->get_variations() as $variation_object) { $variation_object->set_stock_quantity(1); $variation_object->set_stock_status('instock'); $variation_object->save(); } // 发布新产品 $new_product->set_status('publish'); $new_product->save(); echo '<script>console.log("This product has sold out!");</script>'; } else { echo '<script>console.log("This product still has some options in stock!");</script>'; } } } add_action('woocommerce_thankyou', 'order_checker', 10, 1);
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

