返回

WooCommerce批量定价: 不同分类商品总数分级定价

php

WooCommerce 不同分类商品总数批量定价的解决方案

购物车中不同ID的商品,加起来满足特定数量范围就应用分级价格,这需求听起来有点复杂,别慌,咱们一步步拆解。

一、 问题拆解与原因分析

你想实现的是:将购物车里不同分类(或者更精确地说,不同产品ID)的商品数量加总,根据总数落入哪个区间,来应用不同的单价。

问题关键点

  1. 商品分组: 需要把不同类别的商品(根据ID区分)划分到不同的组(比如你例子中的List A和List B)。
  2. 数量统计: 要统计每个分组的商品总数量。
  3. 分级定价: 预先设定好每个分组的阶梯价格规则。
  4. 价格应用: 根据总数,应用相应的价格到对应分组的商品。

你之前代码的问题出在哪?

  • 第一次尝试: woocommerce_before_cart 这个钩子,时机太早了。它在购物车页面展示之前触发,这时候修改价格可能不稳定, 也容易和其他插件冲突, 导致无法完成订单。
  • 第二种尝试:woocommerce_before_calculate_totals 钩子时机对了,但是你获取的是 get_sale_price() (促销价), 你可能只想影响正常价格 (get_regular_price())。 而且用set_price 会同时影响正常价格与促销价,不严谨。

二、解决方案

咱直接上改进后的代码,然后在代码里详细讲解原理和步骤:

add_action( 'woocommerce_before_calculate_totals', 'custom_bulk_pricing', 20, 1 );

function custom_bulk_pricing( $cart ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // 防重复触发
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // 1. 定义分组和价格规则 (你可以根据需要修改)
    $groups = array(
        'group_a' => array(
            'ids' => array( 351, 916, 825, 528, 527, 524, 192, 190, 188, 186, 184, 182, 180, 178, 70, 68, 66, 64 ),
            'tiers' => array(
                array( 'min' => 1,   'max' => 99,  'price' => 0.20 ),
                array( 'min' => 100, 'max' => 199, 'price' => 0.18 ),
                array( 'min' => 200, 'max' => 99999, 'price' => 0.14 ), // 假设一个很大的上限
            ),
        ),
        'group_b' => array(
            'ids' => array( 4, 5, 6 ), // 示例ID, 替换为你自己的
            'tiers' => array(
                array( 'min' => 1,   'max' => 99,  'price' => 0.30 ),
                array( 'min' => 100, 'max' => 199, 'price' => 0.28 ),
                array( 'min' => 200, 'max' => 99999, 'price' => 0.20 ),
            ),
        ),
        // 还可以添加更多分组...
    );

    // 2. 遍历购物车,统计每个分组的总数量
    $group_totals = array();
    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product_id = $cart_item['product_id'];
        $quantity   = $cart_item['quantity'];

        foreach ( $groups as $group_key => $group ) {
            if ( in_array( $product_id, $group['ids'] ) ) {
                if ( ! isset( $group_totals[ $group_key ] ) ) {
                    $group_totals[ $group_key ] = 0;
                }
                $group_totals[ $group_key ] += $quantity;
                break; // 找到分组就跳出内层循环
            }
        }
    }
     // 3. 再次遍历购物车, 应用价格.
     foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
        $product_id = $cart_item['product_id'];
            //print_r($product_id);
        foreach ( $groups as $group_key => $group ) {
          if ( in_array( $product_id, $group['ids'] ) ) {
                 $total_quantity = $group_totals[ $group_key ];
                $new_price      = null;
                    //print_r($group);
                // 查找对应的价格区间
                foreach ( $group['tiers'] as $tier ) {
                  if ( $total_quantity >= $tier['min'] && $total_quantity <= $tier['max'] ) {
                        $new_price = $tier['price'];
                        break;
                     }
                 }

              if ( $new_price !== null ) {
                    // 仅设置正常价格. 如果想修改其他,请更改 'regular' 到 'sale',或其他价格的key.
                  $cart_item['data']->set_price( $new_price);
                        //$cart_item['data']->set_regular_price($new_price );
                        //$cart_item['data']->set_sale_price($new_price );
                 }

               break; // 找到分组就跳出内层循环
             }
        }
    }
}

代码解释:

  1. 分组与规则定义($groups):

    • 用一个数组来定义所有分组。
    • 每个分组(如group_agroup_b)包含:
      • ids: 该组包含的所有商品 ID。
      • tiers: 该组的价格阶梯。每个阶梯包含:min(最小数量)、max(最大数量)、price(单价)。
  2. 统计分组总数($group_totals):

    • 第一次遍历购物车:对每个商品,判断它属于哪个分组,累加到对应分组的总数。
    • 如果找不到就什么也不做。
  3. 再次遍历并找到对应的组和价格信息

    * 查找对一个的ID并且设置总价。
    * 根据`$group_totals`  的总数找到合适的`$new_price` 。
    * 检查 `$new_price` 是否有找到价格区间
    
  4. 应用价格

    • set_price 设置正常价格。
    • 如果有其他价格设置的需求,更换成其他的set_ 方法即可。
    • 找到对应的id就设置一个对应的总价。

使用方法 & 步骤:

  1. 复制代码: 将上述代码复制到你的主题的 functions.php 文件中(或者通过Code Snippets插件添加)。
  2. 修改配置:
    • $groups 数组中,根据你的实际需求,修改分组的 ID (ids) 和价格阶梯 (tiers)。
    • 可以根据需要,添加更多分组。
  3. 测试: 清空购物车,添加不同分组的商品,看看购物车和结账页面的价格是否正确。

额外建议与进阶技巧

  • 性能优化: 如果你的商品和分组非常多,上述双重循环可能会影响性能。可以考虑用商品ID作为数组的键,直接查找,避免内层循环。
  • 缓存: 如果分组和价格规则不经常变动, 可以考虑将 $groups 数组的结果缓存起来(比如用 WordPress 的 Transients API),减少每次计算的开销。
  • 用户界面: 如果你希望这个功能更灵活,可以在后台添加一个设置页面,让管理员可以方便地配置分组和价格规则,不用每次都修改代码。
  • 排除特定商品: 你可以在循环中添加额外的条件判断,排除某些特定商品(比如特价商品)不参与批量定价。
  • 与促销活动结合 : 你可能需要考虑这个批量定价功能与 WooCommerce 其他促销活动(比如优惠券)的叠加规则。可以在应用价格之前,先获取商品的原始价格,根据需要进行一些计算。

错误处理与调试

如果发现没有效果,价格不对:

  1. 开启调试:wp-config.php 文件中,将 WP_DEBUG 设置为 true,开启调试模式,可能会显示错误信息。
  2. 检查代码: 仔细检查 $groups 数组中的 ID 和价格规则是否正确。
  3. 检查商品ID:print_r($product_id) 语句,确保正确的判断每个商品的所属分组。

祝你顺利实现 WooCommerce 的批量定价功能!