返回

WooCommerce: 购物车商品价格动态调整 | 自定义加价最佳实践

php

WooCommerce 购物车商品自定义价格调整

购物车商品价格调整是一个常见的需求,比如基于用户选择或特定条件添加额外费用。 简单地使用update_post_meta直接修改商品价格并不可取,这会导致价格的持久化修改,并且不是针对购物车的即时调整。正确方法是通过 WooCommerce 提供的钩子和函数,在购物车级别进行价格修改。

理解问题根源

核心问题是:如何让自定义的价格调整仅影响购物车内的商品,而不是直接修改产品本身的默认价格。使用update_post_meta修改了商品的_price_regular_price元数据,实际上改变了数据库中的产品定价。 我们需要的是一种仅影响当前购物车商品,并且不永久修改商品信息的方案。此外,直接在页面刷新后更新元数据也影响了用户体验,并且增加了风险,比如在多次刷新后可能造成数据错乱。

解决方案一:woocommerce_before_calculate_totals 钩子

woocommerce_before_calculate_totals 是一个非常强大的钩子,在购物车价格计算之前触发。借助此钩子,可以遍历购物车中的每个商品,并对其价格进行自定义修改。这是一个高效且安全的方法。

步骤:

  1. 使用add_action注册一个回调函数,使其在woocommerce_before_calculate_totals钩子触发时执行。
  2. 在该回调函数中,遍历购物车中的所有商品项。
  3. 针对每个商品项,获取自定义的价格信息。
  4. 使用 WC_Cart_Item 对象中的 set_price() 方法来设置新的价格。

代码示例:

function custom_adjust_cart_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
        return;
    }

    if ( empty( $cart->get_cart() ) ) {
        return;
    }

    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
       $product = $cart_item['data'];

        // 获取你的自定义价格逻辑, 假设这里 $frame_price 是自定义添加的价格
        $frame_price = get_frame_price($cart_item); // 自定义函数根据商品/cart item 获取自定义价格

        if ($frame_price) {
            $custom_price = $product->get_price() + $frame_price;
             //使用 WC_Cart_Item 的 set_price() 方法设置价格
             $cart_item['data']->set_price( $custom_price );

         }


    }
}

add_action( 'woocommerce_before_calculate_totals', 'custom_adjust_cart_item_price' );


//这是一个示例的 get_frame_price() 函数,需要替换成你的逻辑
function get_frame_price( $cart_item ) {
  $product_id = $cart_item['product_id'];
  $variation_id = $cart_item['variation_id'] ? $cart_item['variation_id'] : 0 ;


    //  假设我们的额外价格保存在名为 ‘_number_field’  的产品或变体 meta 中
  if ($variation_id) {
    $price_from_meta = get_post_meta( $variation_id, '_number_field', true);

  } else {
     $price_from_meta  =  get_post_meta( $product_id, '_number_field', true);
  }



  return  floatval($price_from_meta);
}

代码解释:

  • custom_adjust_cart_item_price: 此函数遍历购物车项目,提取商品和 frame_price(通过自定义的 get_frame_price函数获取),并将它们用于计算总价,通过set_price修改购物车内的价格。
  • is_admin() && ! defined( 'DOING_AJAX' ): 这段代码确保修改只在前端发生,并避免在后台或者Ajax请求中执行此函数。
  • empty( $cart->get_cart() ): 当购物车为空时,直接退出,避免遍历错误。
  • get_frame_price(): 需要自定义,返回对应购物车项目自定义增加的价格。这里提供了一个基本示例,假定 _number_field 存储额外价格,从商品或者商品变体中提取。
  • floatval(): get_post_meta 获取到的 meta 值是字符串, 所以用 floatval() 函数进行类型转换, 避免后续计算时发生错误。
  • $cart_item['data']->set_price( $custom_price ): 这行代码才是重点,使用WC_Product 对象的 set_price() 函数改变当前购物车商品项的价格,并且只修改了当前购物车实例中的价格,不会持久化到数据库。

注意事项

  • get_frame_price 函数必须根据自己的实际逻辑实现, 从订单,session, cookie,自定义元数据等中提取对应的额外价格信息。示例代码只提供了一种根据 product 或 variation meta获取的方法,需要调整。
  • 避免在同一个请求多次修改同一个购物车项的价格,例如避免对同一个项目循环设置多个价格。

通过此方案,可以将自定义的价格信息应用于购物车,而不会修改产品本身的定价,并且操作是在购物车价格计算前进行的,对购物车流程的兼容性更好。这种方式更加符合WooCommerce最佳实践,也更加健壮和易于维护。

没有需要补充的相关资源链接。