【问题标题】:Change cart items subscription properties values before checkout在结帐前更改购物车项目订阅属性值
【发布时间】:2019-09-19 08:31:38
【问题描述】:

这可能是一个菜鸟问题,所以提前道歉。

我有可变订阅产品,其价格因订阅长度而异。我也有订阅长度 = 0 的简单订阅。当购物车包含这两种类型时,Woocommerce 订阅会创建两个订阅。

我正在尝试修改购物车中所有商品的 subscription_length 元数据以匹配购物车中的最长长度,因此只会创建一个订阅。

我似乎无法找到更新购物车的正确方法。这可能只是愚蠢的人类 PHP 技巧。

这是该语句的最新变体,但现在不起作用:

$cart[$item_key]['data']->subscription_length = $maxlength;

我已经尝试了十几个或更多主题的变体来更新 $cart 数据。有些失败,有些成功,但 $cart 中的数据没有改变。

function csi_align_subscription_length() {
    $maxlength = 0;
    $cart = WC()->cart->get_cart();

    //find the longest length
    foreach ( $cart as $item_key => $item ){
        if ( WC_Subscriptions_Product::is_subscription( $item['data'] ) ) {
            $length = WC_Subscriptions_Product::get_length( $item['data'] );
            $maxlength = ($length > $maxlength) ?  $length : $maxlength ;   //get the longest length
        }
    }   

    //set all subscription lengths to the longest lengths
    foreach ( $cart as $item_key => $item ){
        if ( WC_Subscriptions_Product::is_subscription( $item['data'] ) ) {
            echo '<pre>';
            echo "cart-item before: ". var_dump($cart[$item_key]);
            $cart[$item_key]['data']->subscription_length = $maxlength;
            echo "cart-item after:  ".var_dump($cart[$item_key]);
            echo '</pre>';
        }
    }   
    WC()->cart->set_cart_contents($cart);
}
add_filter( 'woocommerce_subscription_cart_before_grouping', 'csi_align_subscription_length', 10, 1 );

我只需要将购物车中的订阅与一个公共组对齐,因此每次结帐时我只有 1 个订单和 1 个订阅。如果我迷失在切线上,我愿意采用不同的方法。

【问题讨论】:

    标签: php methods woocommerce cart woocommerce-subscriptions


    【解决方案1】:

    更新 (适用于简单订阅和订阅变体(可变订阅)

    钩子woocommerce_before_calculate_totals 允许更改购物车项目的产品属性。由于woocommerce 3 and CRUD Objects,无法直接访问对象属性,您将不得不使用可用的getter 和setter 方法来代替......这里我们:

    1. 仅获取所有订阅购物车项目的长度数组。
    2. 获取最大长度值
    3. 仅为所有订阅购物车项目设置最大长度值。

    所需代码:

    add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals_action_callback', 10, 1 );
    function before_calculate_totals_action_callback( $cart ) {
        if ( ( is_admin() && ! defined( 'DOING_AJAX' ) )  )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        $maxlength = []; // Initializing
    
        // First loop (get)
        foreach ( $cart->get_cart() as $cart_item ){
            if ( in_array( $cart_item['data']->get_type(), array('subscription', 'subscription_variation') ) ) {
                $maxlength[] = (float) $cart_item['data']->get_length();
            }
        }
    
        // Get the highest value
        $maxlength = max($maxlength);
    
        // Second loop (set)
        foreach ( $cart->get_cart() as $cart_item ){
            if ( is_a( $cart_item['data'], 'WC_Product_Subscription' ) || is_a( $cart_item['data'], 'WC_Product_Subscription_Variation' ) ) {
                $cart_item['data']->set_length( $maxlength );
            }
        }
    }
    

    代码进入您的活动子主题(或活动主题)的 function.php 文件中。经过测试并且可以工作。

    注意:在提交订单时,您肯定需要将购物车商品(自定义)长度设置为自定义订单商品元数据。

    【讨论】:

    • 提供的解决方案不适用于可变订阅。 get_length() 返回一个空字符串。 ` Pre set_length() obj->get_length() = string(0) "" class::get_length() = string(1) "6" Pre set_length() obj->get_length() = string(0) "" class ::get_length() = int(0) 发布 set_length() obj->get_length() = string(0) "" class::get_length() = string(1) "6" 发布 set_length() obj->get_length( ) = string(1) "6" class::get_length() = int(0)` 我更改了代码以使用返回正确值的 class::methods 但购物车值仍然相同 Pre/Post
    • Ran out of room - ->set_length 调用前的长度值与 set_length 调用后的值相同。我遇到了同样的问题。
    • @AV8R 抱歉... 更新:现在适用于简单和可变的订阅。
    • 我很欣赏尝试解决方案,但原始问题仍然存在。您示例中的 set_length() 方法继承自父 WC_Product 类。 'subscription_length' 没有设置方法。 set_length() 方法继承自 WC_Product 并设置产品的尺寸长度(高度、宽度、长度)。我曾尝试使用 update_meta_data() 方法,但它也失败了。方法执行,但数据永远不会改变。
    【解决方案2】:

    终于解决了这个问题。 'subscription_length' 没有设置器。不得不使用 update_meta_data 方法。元键是“_subscription_length”。以下代码有效。

    function csi_align_subscription_length( $cart ) {
        if ( ( is_admin() && ! defined( 'DOING_AJAX' ) )  )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        $maxlength = (float) 0;
    
        // Find the longest subscription length
        foreach ( $cart->get_cart() as $cart_item ){
            if ( is_a( $cart_item['data'], 'WC_Product_Subscription' ) || is_a( $cart_item['data'], 'WC_Product_Subscription_Variation' ) ) {
                $length = (float) WC_Subscriptions_Product::get_length( $cart_item['data'] );
                $maxlength = ($length > $maxlength) ?  $length : $maxlength ;   //get the longest length
            }
        } 
    
        // set the subscription length for everything in the cart
        foreach ( $cart->get_cart() as $item_key => $cart_item ){
            if ( is_a( $cart_item['data'], 'WC_Product_Subscription' ) || is_a( $cart_item['data'], 'WC_Product_Subscription_Variation' )) {
                $cart_item['data']->update_meta_data( '_subscription_length', $maxlength );
            }
        }
    }
    
    add_action( 'woocommerce_before_calculate_totals', 'csi_align_subscription_length', 5, 1 );
    
    

    【讨论】:

    • 不错的答案 (+1)...所以我的代码在某些方面有点用处。
    • 是的,当然。我将其从 woocommerce_subscription_cart_before_grouping 过滤器移至 woocommerce_before_calculate_totals 操作。无论如何,它更适合这里。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 2019-06-27
    相关资源
    最近更新 更多