如何为WooCommerce商品按日期属性设置独立库存上限?
问题描述
我用WordPress的WooCommerce插件售卖活动门票,商品设置了「水瓶颜色」和「活动日期」两个属性,用户必须选完这两个属性才能加购。已经创建了对应变体,但现在需要每个活动日期单独设置100张的库存上限,且这个上限不受水瓶颜色影响。
直接给每个变体设库存会出问题:比如「红色-第一天」「蓝色-第一天」「绿色-第一天」各设100库存,第一天总库存就变成300了,不符合需求。
附我尝试的代码:
// Add filter to manage stock quantity for date variations on product #6239 add_filter('woocommerce_variation_sale_price', 'custom_manage_date_stock_quantity_product_6239', 10, 3 ); add_filter('woocommerce_variation_price', 'custom_manage_date_stock_quantity_product_6239', 10, 3 ); add_filter('woocommerce_product_variation_get_regular_price', 'custom_manage_date_stock_quantity_product_6239', 10, 3 ); add_filter('woocommerce_product_variation_get_sale_price', 'custom_manage_date_stock_quantity_product_6239', 10, 3 ); function custom_manage_date_stock_quantity_product_6239( $price, $variation, $product ) { // Check if the variation belongs to product #6239 if ( $product->get_id() === 6239 ) { $date_attribute = $variation['attributes']['Date']; // Replace 'attribute_date' with the actual slug of the Date attribute // Set stock quantity based on the date attribute switch ( $date_attribute ) { case 'Saturday': $stock_quantity = 100; // Set the stock limit for this specific date break; case 'Sunday': $stock_quantity = 100; break; // Add more cases for other date options and their respective stock limits default: $stock_quantity = 0; // No stock for other date options } // Apply the stock quantity only for Date variations if ( isset($variation['attributes']['Date']) ) { $variation['max_qty'] = $stock_quantity; $variation['stock_quantity'] = $stock_quantity; } } return $price; }
问题分析
你用了价格相关的钩子来修改库存,这完全不对路——这些钩子只负责处理价格输出,根本不会影响WooCommerce的库存逻辑。而且直接修改$variation数组也没用,因为WooCommerce里的变体是WC_Product_Variation对象,不是普通数组,你这么改不会被系统识别。另外,你没有处理同日期下所有变体的已售数量总和,也没做加购时的库存验证,所以根本实现不了共享库存的效果。
解决方案
要实现「同日期所有颜色共享100库存」的需求,需要从三个方面入手:计算已售总量、限制最大购买数、加购时验证库存。
步骤1:基础设置
- 给父产品(ID=6239)开启「管理库存」,但不要给任何变体单独设置库存(或者把所有变体库存设为0,因为我们要自定义库存逻辑)。
- 确保「活动日期」属性的slug是
pa_date(WooCommerce属性默认前缀是pa_,你可以在后台属性编辑页查看实际slug)。
步骤2:自定义代码
把下面的代码添加到主题的functions.php文件或者自定义插件里:
// 计算指定日期的总已售数量 function get_total_sold_for_date( $product_id, $date_value ) { $args = array( 'status' => array('wc-completed', 'wc-processing'), // 只统计已完成/处理中的订单 'limit' => -1, 'meta_query' => array( array( 'key' => '_product_id', 'value' => $product_id, 'compare' => '=' ) ), 'line_item_type' => 'line_item' ); $orders = wc_get_orders($args); $total_sold = 0; foreach ($orders as $order) { foreach ($order->get_items() as $item) { $variation = $item->get_variation(); if (!$variation) continue; // 获取变体的活动日期属性值 $item_date = $variation->get_attribute('pa_date'); if ($item_date === $date_value) { $total_sold += $item->get_quantity(); } } } return $total_sold; } // 设置变体的最大可购买数量 add_filter('woocommerce_available_variation', 'set_date_based_max_qty', 10, 3); function set_date_based_max_qty( $args, $product, $variation ) { $target_product_id = 6239; if ($product->get_id() !== $target_product_id) return $args; // 获取当前变体的活动日期值 $date_value = $variation->get_attribute('pa_date'); if (empty($date_value)) return $args; $total_stock = 100; // 每个日期的总库存上限 $total_sold = get_total_sold_for_date($target_product_id, $date_value); $remaining_stock = $total_stock - $total_sold; // 设置最大可购买数量,不能超过剩余库存 $args['max_qty'] = max(0, $remaining_stock); // 显示剩余库存提示 $args['availability_html'] = '<p class="stock in-stock">剩余库存:' . $remaining_stock . ' 张</p>'; return $args; } // 加购时验证库存是否足够 add_filter('woocommerce_add_to_cart_validation', 'validate_date_based_stock', 10, 5); function validate_date_based_stock( $passed, $product_id, $quantity, $variation_id = 0, $variations = array() ) { $target_product_id = 6239; if ($product_id !== $target_product_id) return $passed; if ($variation_id > 0) { $variation = wc_get_product($variation_id); $date_value = $variation->get_attribute('pa_date'); if (empty($date_value)) return $passed; $total_stock = 100; $total_sold = get_total_sold_for_date($target_product_id, $date_value); $remaining_stock = $total_stock - $total_sold; if ($quantity > $remaining_stock) { wc_add_notice('该日期剩余库存不足,最多可购买 ' . $remaining_stock . ' 张', 'error'); $passed = false; } } return $passed; }
代码说明
get_total_sold_for_date:统计指定产品、指定日期下所有变体的已售总量,只计算已完成和处理中的订单,避免退款或取消订单影响库存统计。set_date_based_max_qty:在变体加载时,计算对应日期的剩余库存,设置该变体的最大可购买数量,并显示剩余库存提示。validate_date_based_stock:用户加购时,验证购买数量是否超过该日期的剩余库存,不足则提示错误并阻止加购。
注意事项
- 替换代码中的
pa_date为你实际的「活动日期」属性slug(后台进入产品属性编辑页,查看属性的「slug」字段)。 - 如果需要给不同日期设置不同库存上限,可以修改
$total_stock的值,比如用switch-case根据$date_value设置不同数值。
内容的提问来源于stack exchange,提问作者SkyT
相关产品推荐
相关产品推荐

