You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 22:36:04