WooCommerce Per Product Shipping插件仅收最高运费代码报错求助
问题:WooCommerce Per Product Shipping插件实现仅收取最高产品运费时触发致命错误
我使用WooCommerce Per Product Shipping插件按产品设置运费,该插件无内置功能实现类似WooCommerce核心平邮的计算逻辑——仅收取整单中运费最高的产品的运费。我尝试用AI生成的代码实现,但操作后始终触发致命错误。
插件与产品设置说明
- 插件设置:税务状态为应税;未设置默认产品运费、单产品或整单手续费;未勾选「忽略其他配送方式」;未启用其他配送方式
- 产品设置:已启用按产品配送;为美国本土、夏威夷、阿拉斯加三个地区分别添加了运费条目
原AI生成代码(触发错误)
/** * Retrieve shipping costs for a WooCommerce product. * * @param int $product_id The ID of the WooCommerce product. * @return float|null Shipping cost for the product, or null if not found. */ function get_shipping_cost_for_product( $product_id ) { $shipping_methods = WC()->shipping->get_packages(); foreach ( $shipping_methods as $package ) { foreach ( $package['rates'] as $rate ) { // Check if the shipping rate is applicable to the product. if ( $rate->method_id === '11' && $rate->get_instance_id() === 0 ) { // Retrieve the shipping cost for the product. return $rate->cost; } } } return null; // Shipping cost not found. } /** * Custom function to calculate shipping costs for WooCommerce Per Product Shipping. * * @param array $package Shipping package. * @return void */ function custom_per_product_shipping_cost( $package ) { if ( ! is_array( $package['contents'] ) ) { return; } // Initialize variables to keep track of the highest shipping cost. $highest_shipping_cost = 0; // Loop through each item in the cart. foreach ( $package['contents'] as $item_id => $item ) { $product_id = $item['product_id']; // Get the shipping cost for the current product. $shipping_cost = get_shipping_cost_for_product( $product_id ); // Compare with the highest shipping cost found so far. if ( $shipping_cost > $highest_shipping_cost ) { $highest_shipping_cost = $shipping_cost; } } // Set the calculated highest shipping cost for the entire order. $package['contents_cost'] = $highest_shipping_cost; // Update the package shipping costs. WC()->cart->shipping_total = $highest_shipping_cost; WC()->cart->shipping_tax_total = 0; // You may need to adjust tax calculation. WC()->cart->shipping_taxes = array(); WC()->cart->shipping_methods = array(); // Recalculate cart totals. WC()->cart->calculate_totals(); } // Hook into the shipping calculation process. add_action( 'woocommerce_cart_shipping_packages', 'custom_per_product_shipping_cost' );
问题分析
- 钩子使用错误:
woocommerce_cart_shipping_packages是过滤器(需返回修改后的数据),原代码用动作钩子且未返回包裹数组,导致循环计算触发致命错误 - 运费获取逻辑失效:硬编码
method_id === '11'不通用,且依赖未完成计算的包裹费率,无法准确读取产品运费设置 - 直接修改购物车属性:调用
WC()->cart->calculate_totals()会重新触发运费计算,造成无限循环
修正后的代码
/** * 获取指定产品对应配送区域的运费(适配WooCommerce Per Product Shipping插件) * * @param int $product_id 产品ID * @param array $package 配送包裹(包含用户地址信息) * @return float 产品运费 */ function get_per_product_shipping_cost( $product_id, $package ) { $shipping_cost = 0; $shipping_zones = WC_Shipping_Zones::get_zones(); $customer_location = $package['destination']; // 匹配用户所在配送区域 foreach ( $shipping_zones as $zone ) { $is_match = WC_Shipping_Zones::location_matches_zone( $customer_location, $zone['zone_locations'] ); if ( $is_match ) { $product_shipping = get_post_meta( $product_id, '_per_product_shipping', true ); if ( is_array( $product_shipping ) && isset( $product_shipping[ $zone['zone_id'] ] ) ) { $shipping_cost = (float) $product_shipping[ $zone['zone_id'] ]['cost']; break; } } } // 匹配默认区域运费 if ( $shipping_cost === 0 ) { $product_shipping = get_post_meta( $product_id, '_per_product_shipping', true ); if ( is_array( $product_shipping ) && isset( $product_shipping[0] ) ) { $shipping_cost = (float) $product_shipping[0]['cost']; } } return $shipping_cost; } /** * 定制Per Product Shipping计算逻辑:仅收取最高产品运费 * * @param array $packages 配送包裹数组 * @return array 修改后的包裹数组 */ function custom_per_product_shipping_highest_cost( $packages ) { if ( empty( $packages ) ) return $packages; $highest_shipping_cost = 0; // 遍历包裹商品,找出最高运费 foreach ( $packages as &$package ) { if ( empty( $package['contents'] ) ) continue; foreach ( $package['contents'] as $item ) { $item_shipping_cost = get_per_product_shipping_cost( $item['product_id'], $package ); if ( $item_shipping_cost > $highest_shipping_cost ) { $highest_shipping_cost = $item_shipping_cost; } } // 更新Per Product Shipping费率为最高运费 if ( $highest_shipping_cost > 0 ) { foreach ( $package['rates'] as $rate_id => $rate ) { if ( $rate->method_id === 'per_product' ) { $package['rates'][ $rate_id ]->cost = $highest_shipping_cost; // 同步计算运费税费 $taxes = WC_Tax::calc_shipping_tax( $highest_shipping_cost, WC()->tax()->get_shipping_tax_rates() ); $package['rates'][ $rate_id ]->taxes = $taxes; } } } } return $packages; } add_filter( 'woocommerce_cart_shipping_packages', 'custom_per_product_shipping_highest_cost' );
代码关键改进
- 使用过滤器钩子并正确返回包裹数组,避免循环计算
- 直接读取插件存储的产品元数据运费,逻辑更稳定可靠
- 自动匹配用户所在配送区域的运费设置,覆盖默认区域场景
- 修改现有费率成本而非直接操作购物车属性,避免冲突
- 保留税费计算逻辑,适配插件应税设置
内容的提问来源于stack exchange,提问作者Janna Hartley
相关产品推荐
相关产品推荐

