在 WooCommerce 中设置每个购物车项目的运输方式

时间:2021-02-17 13:15:21

标签: wordpress woocommerce hook-woocommerce

我工作的一家在线商店使用 2 种运输方式:基于尺寸的费率和本地取货。

基于尺寸的费率是默认的运输方式,只有当客户点击点击并取货而不是添加到购物车时,才会使用本地取货(在内部,产品是在这两种情况下都添加到购物车中,但在使用点击取货时,会添加额外的购物车项目数据以表明这一点)。

在使用点击取货预订所有购物车商品时计算总运费没有问题,因为您可以在运行时使用过滤器 woocommerce_package_rates 过滤运费并更改运费方法,因此它会影响所有购物车项目。

但是,如果购物车包含同时添加点击取货添加到购物车的商品,则计算总运费会变得更加困难,因为运费必须为每个购物车项目更改方法,并且不会影响所有购物车项目。

所需的流量:

<块引用>

购物车商品: 3
预订 x 2 通过点击和取货预订(成本:0,本地取货运输方式)
纸 x 1 以正常方式添加到购物车,(成本:默认尺寸费率,默认运输方式)
总运费:本地取件费用 + 默认运费

当前代码:

function cust_shipping_rates( $rates, $package ) {
   if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

   $product_ids_with_local_pickup = array(); // 'click and pickup'
   
   // Loop through line items
   foreach( $package['contents'] as $line_item ) {
       // Get product id
       $product_id = $line_item['product_id'];
   
       if ( $line_item['sofs_cap'] ) { // indication it's reserved with 'Click and pick'
         array_push($product_ids_with_local_pickup, $product_id);
       }
   }
   
   if ( count($product_ids_with_local_pickup) > 0 ) {
       foreach ( $rates as $rate_key => $rate ) {
           if ( in_array( $rate->method_id, array( 'bring_fraktguiden:5800' ) ) ) { // default shipping method
               // how can i exclude the reserved products from being affected by this shipping method?
               $rates[$rate_key]->set_cost(/* cost */); // changing this affects ALL items, not just the specific ones
           }
       }
   }
   
   return $rates;
}

add_filter('woocommmerce_package_rates', 'cust_shipping_rates', 999, 2);

1 个答案:

答案 0 :(得分:0)

这个答案没有解释如何为每个产品添加不同的运输方式,this plugin 可以帮助解决这个问题 - 但是,如果您需要从计算运费中排除某些购物车项目,这个答案可能对您有所帮助。

过滤器 woocommerce_cart_shipping_packages 返回一个 包裹,其中包含过滤器 woocommerce_package_rates 中的运输方式迭代以计算运输成本的购物车项目。

通过在返回的包裹中过滤购物车,像这样简单地删除您不希望运送的购物车项目:

// define the woocommerce_cart_shipping_packages callback 
function filter_woocommerce_cart_shipping_packages( $package ) { 
    $new_cart = $package[0]['contents'];

    foreach($cart as $cart_item) {
       // check for desired shipping method
       // cart items not checking for this property, will not be accounted for shipping costs
       if($cart_item['custom_extra_cart_item_data']) {
          array_push($new_cart, $cart_item); 
       } 
    }

    if(!empty($new_cart)) $package[0]['contents'] = $new_cart;

    return $package; 
}; 
         
// add the filter 
add_filter( 'woocommerce_cart_shipping_packages', 'filter_woocommerce_cart_shipping_packages', 10, 1 ); 

这是我的案例的代码(键名 sofs_cap 是属于唯一购物车项目的额外购物车项目数据,表明它是用 click and pick 添加的,您的键名可以是任何你喜欢的)。

<块引用>

注意:就我而言,我至少需要一种运输方式才能 查看。所以当购物车只包含不符合资格的项目时 运输 - 我只是将运输方式设置为“本地取货”(即 也很合适)。我还排除了该运输方式时 购物车有两种方式添加的项目。

function custom_shipping_rates($rates, $pkg) {
   if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

   $has_cap = false; // added with click and pikcup
   $has_def = false; // added default way
   
   // Loop through line items
   foreach( $pkg['contents'] as $line_item ) {
      if($line_item['sofs_cap']) $has_cap = true; else $has_def = true;
   }

   $new_rates = array();

   if($has_cap && $has_def || $has_def) { // cart with items added both ways returns all shipping methods except local pickup
      foreach ($rates as $rate_key => $rate ) {
         if($rate_key !== 'local_pickup:8') { // id can be different for your shipping method
            $new_rates[$rate_key] = $rate;
         }
     }

     return $new_rates;
   } else if ($has_cap) {  // cart with only items added with Click and pickup returns only shipping method local pickup
      $new_rates['local_pickup:8'] = $rates['local_pickup:8'];
      return $new_rates;
   } 

   return $rates;
}
add_filter('woocommerce_package_rates', 'custom_shipping_rates', 999, 2);

function custom_filtered_cart_shipping_packages( $shipping_package ) {
    $new_cart = array(); // only contains cart items that are not added with 'Click and pickup'
    $has_cap_added_items = false;
    
    foreach($shipping_package[0]['contents'] as $cart_item) {
        if(!$cart_item['sofs_cap']) {
            array_push($new_cart, $cart_item); // add only default added products to the package
        } else {
            $has_cap_added_items = true;
        }
    }

    $shipping_package[0]['contents'] = $new_cart;
      
    return $shipping_package; 
}
      
add_filter( 'woocommerce_cart_shipping_packages', 'custom_filtered_cart_shipping_packages');