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

WooCommerce 8.6.1:特定配送区域改配送类代码无效果排查

WooCommerce 8.6.1 配送类修改代码无效问题排查与修复

问题背景

需求为:结账时,若客户处于指定配送区域(ID 29),且购物车中至少有2个属于特定配送类(ID 343)的商品,需将这些商品的配送类改为ID 344。提供的代码未产生预期效果,已排除插件、其他代码片段、主题兼容性问题。

原代码:

// Custom function to change shipping class if conditions are met
function adjust_shipping_class_based_on_quantity() {
    // Get the current cart contents
    $cart = WC()->cart->get_cart();

    // Check if the cart contains items and the first item has a destination
    if ( ! empty( $cart ) && isset( $cart[0]['destination'] ) && is_array( $cart[0]['destination'] ) ) {
        // Get the shipping zone ID
        $zone_id = WC_Shipping_Zones::get_zone_matching_package( array( 'contents' => $cart ) )->get_id();

        // Check if the shipping zone ID is 29
        if ( $zone_id == 29 ) {
            // Initialize variables to count 'Letter box' items
            $letter_box_count = 0;

            // Loop through cart items to count 'Letter box' items
            foreach( $cart as $item ) {
                if ( isset( $item['data'] ) && $item['data']->get_shipping_class_id() == 343 ) {
                    // Increment count for each 'Letter box' item
                    $letter_box_count += $item['quantity'];
                }
            }

            // If there are at least 2 'Letter box' items, change shipping class of all 'Letter box' items to 344
            if ( $letter_box_count >= 2 ) {
                // Loop through cart items again to change shipping class if shipping class ID is 343
                foreach( $cart as $key => $item ) {
                    if ( isset( $item['data'] ) && $item['data']->get_shipping_class_id() == 343 ) {
                        // Change the shipping class of the item to 'regular-package'
                        $cart[$key]['data']->set_shipping_class_id(344);
                    }
                }
            }

            // Set the modified cart contents
            WC()->cart->set_cart( $cart );
        }
    }
}
add_action( 'woocommerce_cart_loaded_from_session', 'adjust_shipping_class_based_on_quantity' );

问题根源分析

  1. 配送区域获取逻辑错误

    • 购物车项(cart item)中不存在destination键,原代码通过$cart[0]['destination']判断配送地址存在的逻辑不成立,配送地址信息存储在会话的配送包裹数据中。
    • 调用WC_Shipping_Zones::get_zone_matching_package时,传入的参数缺少destination字段,导致无法正确匹配配送区域。
  2. 钩子时机不合适

    • woocommerce_cart_loaded_from_session仅在购物车从会话加载时触发,无法响应结账过程中用户修改收货地址的场景,导致条件判断无法实时更新。
  3. 购物车数据更新逻辑错误

    • 修改商品配送类后,调用WC()->cart->set_cart($cart)属于冗余操作,且未触发购物车重新计算,导致修改后的配送类无法生效。

修复后的代码

function adjust_shipping_class_based_on_shipping_zone_and_quantity() {
    // 确保WC Cart对象存在且非空
    if ( ! WC()->cart || WC()->cart->is_empty() ) {
        return;
    }

    // 获取完整的配送包裹信息
    $shipping_package = WC()->cart->get_shipping_packages()[0] ?? null;
    if ( ! $shipping_package || empty( $shipping_package['destination'] ) ) {
        return;
    }

    // 匹配当前配送区域,捕获异常避免未设置地址时报错
    try {
        $shipping_zone = WC_Shipping_Zones::get_zone_matching_package( $shipping_package );
        $zone_id = $shipping_zone->get_id();
    } catch ( Exception $e ) {
        return;
    }

    // 检查是否为目标配送区域ID 29
    if ( $zone_id != 29 ) {
        return;
    }

    // 统计目标配送类(ID 343)的商品总数量
    $target_class_count = 0;
    foreach ( WC()->cart->get_cart() as $item ) {
        if ( isset( $item['data'] ) && $item['data']->get_shipping_class_id() == 343 ) {
            $target_class_count += $item['quantity'];
        }
    }

    // 数量不足2则终止
    if ( $target_class_count < 2 ) {
        return;
    }

    // 修改符合条件的商品配送类为ID 344
    foreach ( WC()->cart->get_cart() as $key => $item ) {
        if ( isset( $item['data'] ) && $item['data']->get_shipping_class_id() == 343 ) {
            $item['data']->set_shipping_class_id(344);
            // 标记购物车内容已变更
            WC()->cart->cart_contents_changed = true;
        }
    }

    // 触发购物车重新计算,确保变更生效
    WC()->cart->calculate_totals();
}
// 在购物车计算前和结账配送方式更新时触发,覆盖全场景
add_action( 'woocommerce_before_calculate_totals', 'adjust_shipping_class_based_on_shipping_zone_and_quantity', 20 );
add_action( 'woocommerce_checkout_update_shipping_method', 'adjust_shipping_class_based_on_shipping_zone_and_quantity' );

代码说明

  • 正确获取配送区域:通过WC()->cart->get_shipping_packages()获取包含配送地址的完整包裹数据,确保get_zone_matching_package能准确匹配配送区域。
  • 覆盖全场景钩子:使用woocommerce_before_calculate_totals和woocommerce_checkout_update_shipping_method两个钩子,覆盖购物车修改、结账地址变更等所有需要触发逻辑的场景。
  • 确保变更生效:标记购物车内容变更并调用calculate_totals(),强制WooCommerce重新计算购物车数据,使修改的配送类生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 21:57:46