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

调用结算页通过URL添加多商品前,WooCommerce购物车清空失败

问题:WooCommerce中调用WC()->cart->empty_cart()无法清空购物车的原因及解决办法

我通过以下代码实现了通过URL(格式如...com/checkout/?add-to-cart=632:11,422:7)直接跳转到结算页并添加多个商品,但调用WC()->cart->empty_cart();时,无论用户是否登录,都无法清空购物车,请问这是什么原因?

// 允许通过如下格式的URL向结算页或购物车添加多商品 ...com/checkout/?add-to-cart=632:11,422:7
function add_multiple_products_to_cart_9R_M2asdf() {
    // 确保已安装WooCommerce,且存在格式正确的'add-to-cart'查询参数。
    if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
        return;
    }

    // 添加新商品前清空购物车,否则会追加到已有商品中...
    WC()->cart->empty_cart();
    
    // 移除WooCommerce默认的add_to_cart_action钩子。
    remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

    // 拆分商品ID和数量。
    $product_entries = explode( ',', sanitize_text_field( $_REQUEST['add-to-cart'] ) );

    foreach ( $product_entries as $entry ) {
        // 将每个条目拆分为商品ID和数量。
        list($product_id, $quantity) = array_map('absint', explode( ':', $entry ) + [null, 1]);

        if ( ! $product_id ) {
            continue;
        }

        // 在请求中设置数量。
        $_REQUEST['quantity'] = $quantity;

        // 使用WooCommerce默认方法处理最后一个商品。
        if ( end($product_entries) === $entry ) {
            $_REQUEST['add-to-cart'] = $product_id;
            return WC_Form_Handler::add_to_cart_action();
        }

        // 处理商品。
        $product_id = apply_filters( 'woocommerce_add_to_cart_product_id', $product_id );
        $product = wc_get_product( $product_id );

        if ( ! $product ) {
            continue;
        }

        $add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $product->get_type(), $product );

        // 处理不同类型的商品。
        if ( 'variable' === $add_to_cart_handler ) { // 可变商品
            woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id );
        } elseif ( 'grouped' === $add_to_cart_handler ) { // 分组商品
            woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id );
        } elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ) { // 自定义处理器
            do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler );
        } else { // 简单商品
            woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id );
        }
    }
}
add_action( 'wp_loaded', 'add_multiple_products_to_cart_9R_M2asdf', 15 );

/**
 * 调用类的私有方法。
 *
 * @param string $class_name
 * @param string $method_name
 * @param mixed  ...$args
 * @return mixed
 */
function woo_invoke_private_method_93gK_M3q( $class_name, $method_name, ...$args ) {
    if ( version_compare( phpversion(), '5.3', '<' ) ) {
        throw new Exception( 'PHP版本不支持ReflectionClass::setAccessible()', __LINE__ );
    }

    $reflection = new ReflectionClass( $class_name );
    $method = $reflection->getMethod( $method_name );
    $method->setAccessible( true );

    return $method->invoke( null, ...$args );
}

原因分析

  • 钩子执行时机冲突:当前函数挂载在wp_loaded钩子(优先级15),但WooCommerce会在woocommerce_init或更早阶段从session/cookie恢复购物车数据,导致清空操作后旧数据又被重新加载。
  • session/cookie未同步更新:empty_cart()仅清空了内存中的购物车对象,未主动更新存储用户购物车数据的session(登录用户)或cookie(未登录用户),页面加载后旧数据会被再次读取。
  • 默认方法的逻辑干扰:处理最后一个商品时调用的WC_Form_Handler::add_to_cart_action()内部包含购物车初始化逻辑,会覆盖之前的清空操作。

解决办法

1. 调整钩子执行时机

将函数挂载到更早的woocommerce_init钩子,确保在WooCommerce恢复购物车前执行清空操作:

add_action( 'woocommerce_init', 'add_multiple_products_to_cart_9R_M2asdf', 10 );

在empty_cart()后手动更新session和cookie,确保存储的购物车数据被清空:

WC()->cart->empty_cart();
// 更新session中的购物车数据
WC()->session->set( 'cart', WC()->cart->get_cart() );
// 未登录用户更新购物车hash cookie
if ( ! is_user_logged_in() ) {
    wc_setcookie( 'woocommerce_cart_hash', WC()->cart->get_cart_hash() );
}

3. 统一商品处理逻辑

移除对默认add_to_cart_action()的调用,沿用私有方法处理最后一个商品,避免逻辑冲突:

// 替换原最后一个商品的处理代码
// if ( end($product_entries) === $entry ) {
//     $_REQUEST['add-to-cart'] = $product_id;
//     return WC_Form_Handler::add_to_cart_action();
// }

// 改为和其他商品一致的处理逻辑
$add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $product->get_type(), $product );
if ( 'variable' === $add_to_cart_handler ) {
    woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id );
} elseif ( 'grouped' === $add_to_cart_handler ) {
    woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id );
} elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ) {
    do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler );
} else {
    woo_invoke_private_method_93gK_M3q( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id );
}

4. 确保钩子移除生效

将移除默认add_to_cart_action钩子的代码移到清空购物车之前,避免默认逻辑干扰:

// 先移除默认钩子
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
// 再清空购物车
WC()->cart->empty_cart();

内容的提问来源于stack exchange,提问作者eva last

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:35:06