WooCommerce仅对指定两个产品应用时段购买限制的代码问题
原代码存在的核心问题
- 产品判断逻辑完全失效:调用
woocommerce_variation_is_purchasable、woocommerce_is_purchasable两个过滤器时,未声明需要接收2个入参,导致回调函数根本拿不到当前操作的产品对象;同时误用is_product()做页面级判断,这个函数只能识别当前访问的单产品详情页,在产品列表、购物车等其他场景下无法匹配目标产品ID,规则完全不生效。 - 可购买状态返回逻辑残缺:回调函数仅在匹配到指定产品时返回判断结果,遇到其他产品时无显式返回值,导致WooCommerce将空返回值判定为不可购买,造成全商品被锁死的反向效果。
- 结算校验未关联目标商品:购物车、结算环节的校验只要检测到非营业时段就全量拦截,没有先判断当前购物车是否存在受时间规则限制的商品,把不受限的商品也一并拦了,完全偏离需求。
- 通知展示条件逻辑错误:混写
||和&&运算符未加括号,优先级错乱,会导致关店提示在错误的页面弹出,或者该弹的时候不弹。
修正后的可运行代码
代码将需要受限的产品ID统一抽成独立配置项,后续调整规则仅需修改数组内的ID值即可:
// 自定义营业时段判断函数 function is_shop_open(){ date_default_timezone_set('Europe/Paris'); $start_time = mktime('10', '00', '00', date('m'), date('d'), date('Y')); $end_time = mktime('14', '30', '00', date('m'), date('d'), date('Y')); $now_time = time(); // 允许的工作日:1=周一 5=周五 $allowed_days = in_array( date('N'), array(1, 2, 3, 4, 5) ); return $allowed_days && $now_time >= $start_time && $now_time <= $end_time; } // 定义需要应用时间购买规则的受限产品ID function get_restricted_product_ids() { return array(1, 2); // 替换为实际需要限制的产品ID } // 控制产品可购买状态 add_filter('woocommerce_variation_is_purchasable', 'shop_closed_disable_purchases', 10, 2); add_filter('woocommerce_is_purchasable', 'shop_closed_disable_purchases', 10, 2); function shop_closed_disable_purchases( $purchasable, $product ) { $restricted_ids = get_restricted_product_ids(); // 获取当前判断的产品ID:变体产品取父级ID匹配 $current_product_id = $product->get_type() == 'variation' ? $product->get_parent_id() : $product->get_id(); // 仅对受限产品做时间校验,非受限产品直接返回原状态 if ( in_array( $current_product_id, $restricted_ids ) ) { return is_shop_open() ? $purchasable : false; } // 非受限产品不做拦截 return $purchasable; } // 购物车环节校验 add_action( 'woocommerce_check_cart_items', 'shop_open_allow_checkout' ); add_action( 'woocommerce_checkout_process', 'shop_open_allow_checkout' ); function shop_open_allow_checkout(){ // 营业时段直接放行 if ( is_shop_open() ) return; $restricted_ids = get_restricted_product_ids(); $has_restricted_item = false; // 遍历购物车检查是否有受限产品 foreach ( WC()->cart->get_cart() as $cart_item ) { $cart_product_id = $cart_item['product_id']; if ( in_array( $cart_product_id, $restricted_ids ) ) { $has_restricted_item = true; break; } } // 仅当购物车存在受限产品且非营业时段时,弹出拦截提示 if ( $has_restricted_item ) { wc_add_notice( __("当前非指定商品的可购买时段,相关产品已暂时无法结算", 'woocommerce' ), 'error' ); } } // 展示关店提示 add_action( 'template_redirect', 'shop_is_closed_notice' ); function shop_is_closed_notice(){ // 仅在购物车、结账页,且非营业时段时做后续判断 if ( (is_cart() || is_checkout()) && !is_shop_open() ) { $restricted_ids = get_restricted_product_ids(); $has_restricted_item = false; foreach ( WC()->cart->get_cart() as $cart_item ) { if ( in_array( $cart_item['product_id'], $restricted_ids ) ) { $has_restricted_item = true; break; } } if ( $has_restricted_item ) { wc_add_notice( sprintf( '<span class="shop-closed">%s</span>', esc_html__('指定的限时购买商品当前不在可售时段,其余商品可正常购买结算', 'woocommerce' ) ), 'notice' ); } } }
实现效果
- 只有ID在受限数组里的商品,才会受“周一到周五10:00-14:30可购买”的规则限制,非时段会被标记为不可购买、加购后拦截结算
- 其余所有商品不受时间规则约束,全时段可正常加购、结算,不会被误拦截
- 关店提示仅在购物车/结账页存在受限商品时弹出,不会对其他场景造成干扰
内容的提问来源于stack exchange,提问作者user14906105
相关产品推荐
相关产品推荐

