首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >仅将woocommerce_coupon_get_discount_amount应用于百分比类型优惠券

仅将woocommerce_coupon_get_discount_amount应用于百分比类型优惠券
EN

Stack Overflow用户
提问于 2021-12-11 08:49:57
回答 1查看 1K关注 0票数 1

我创建了以下函数来覆盖产品价格,并为WooCommerce提供最大折扣。然而,我似乎不明白为什么woocommerce_coupon_get_discount_amount过滤器适用于所有优惠券。

我试图让它发挥作用的方法是,如果优惠券是一个百分比的优惠券,它将限制该优惠券的总折扣金额。如果优惠券是fixed_cart类型,并且它有我添加的_price_per_product_amt填充的自定义字段,那么它将改变产品的价格。

如果我在购物车里只有一张优惠券,这两种功能都能工作。如果购物车中有fixed_cart_coupon,它将更改价格并将优惠券金额设置为0美元(优惠券设置为0美元)。但是,如果我也添加了一个百分比优惠券,这个函数可以用于百分比优惠券,但是它也为fixed_cart_coupon添加了一个折扣金额。它只应该修改购物车中的百分比优惠券的折扣金额。

代码语言:javascript
复制
// filter to change discount if over max coupon amount
function filter_woocommerce_coupon_get_discount_amount( $discount, $discounting_amount, $cart_item, $single, $instance ) {

    $cartCoupons = WC()->cart->get_applied_coupons();
    
    foreach ($cartCoupons as $key => $appliedCoupon) {
        $coupon = new WC_Coupon($appliedCoupon);
        $couponType = get_post_meta( $coupon->get_id(), 'discount_type', true );
        if ($couponType == 'percent') {
            $maxCouponAmount = get_post_meta( $coupon->get_id(), '_max_discount', true );
            $excludedProducts = explode(",", get_post_meta( $coupon->get_id(), 'exclude_product_ids', true ));
            $cartLines = count(WC()->cart->get_cart());
            $cartLineItems = WC()->cart->get_cart();

            foreach ($cartLineItems as $cartItem){
                $cartProductID[] = $cartItem['product_id'];

                if (!empty($excludedProducts)) {
                    $cartLinesWithoutExcluded = array_intersect($cartProductID,$excludedProducts);
                } else {
                    $cartLinesWithoutExcluded = $cartProductID;
                }
                $cartLinesWithoutExcluded = count($cartLinesWithoutExcluded);
                $totalCartItems = $cartLines - $cartLinesWithoutExcluded;
                $discount = $maxCouponAmount / $totalCartItems;
            }
        } else {
            $discount = 0.00;
        }

        return $discount;

    }

}

// apply the coupon whether it is max discount or a product price adjustment
function apply_max_amount_or_product_price_adjustment(){

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

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
    return;

    if ( !is_admin() && !wp_is_json_request() ) {
        global $wp, $woocommerce;
        $cartCoupons = WC()->cart->get_applied_coupons();
        foreach ($cartCoupons as $key => $appliedCoupon) {
            $coupon = new WC_Coupon($appliedCoupon);
            $maxCouponAmount = get_post_meta( $coupon->get_id(), '_max_discount', true );
            $excludedProducts = explode(",", get_post_meta( $coupon->get_id(), 'exclude_product_ids', true ));
            $couponType = get_post_meta( $coupon->get_id(), 'discount_type', true );
            // $fixedProductPrice = get_post_meta( $coupon->get_id(), '_adjust_price', true );
            $couponAmount = WC()->cart->get_coupon_discount_amount( $appliedCoupon );

            if (!empty($maxCouponAmount) && $couponType == 'percent' && ($couponAmount > $maxCouponAmount || $couponAmount == $maxCouponAmount)) {
                add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_woocommerce_coupon_get_discount_amount', 10, 5 );
            }

            if ($couponType == 'fixed_cart'){
                $cart = WC()->cart->get_cart();
                $couponProducts = explode(',',get_post_meta( $coupon->get_id(), 'product_ids', true ));
                $fixedPricePerProduct = get_post_meta( $coupon->get_id(), '_price_per_product_amt', true );

                foreach( $cart as $cart_item ) {
                    if (in_array($cart_item['data']->get_parent_id(), $couponProducts)) {
                        $cart_item['data']->set_price( $fixedPricePerProduct );
                    }
                }
            }
        }
    }
}
add_action('woocommerce_before_calculate_totals', 'apply_max_amount_or_product_price_adjustment', 10, 1);
EN

回答 1

Stack Overflow用户

发布于 2021-12-12 01:39:20

我似乎不明白为什么woocommerce_coupon_get_discount_amount过滤器适用于所有优惠券。

这是因为当您从函数'filter_woocommerce_coupon_get_discount_amount‘中添加过滤器'apply_max_amount_or_product_price_adjustment',时,它将被添加到所有优惠券中。稍后会触发此筛选器,因此应用或不应用它的条件将无法工作(因为它已被添加)。您应该删除添加筛选器的部分,并在此函数之外设置筛选器。

在添加任何筛选器时,即使在条件中,由于添加了过滤器,每次都会添加筛选器,直到remove_filter( . )将其删除为止。在您的例子中,您不能在'apply_max_amount_or_product_price_adjustment‘中使用remove_filter,因为它是早期的,并且将为所有的优惠券事件“%”类型删除它。

但是,如果我也添加了百分比优惠券,则该函数适用于百分比优惠券,但它也会向fixed_cart_coupon添加折扣金额。

这是因为您正在循环筛选器'filter_woocommerce_coupon_get_discount_amount‘中的所有优惠券,并且总是从第一个优惠券返回值。这个过滤器每次有$优惠券->get_ fire _amount()时就会触发,因此它会在结帐时触发应用在购物车上的每一张优惠券。您应该删除循环,只检查当前的优惠券。为了更好地理解,您应该将参数'$instance‘重命名为'$coupon’,这是当前的WC_Coupon对象。

您可以查看WC_Coupon类并搜索筛选器'woocommerce_coupon_get_discount_amount‘( ctrl +f以在页面中找到它)如下:https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes/class-wc-coupon.php

此外,在您的循环中要小心:

代码语言:javascript
复制
foreach ($cartLineItems as $cartItem){
    $cartProductID[] = $cartItem['product_id'];

    if (!empty($excludedProducts)) {
        $cartLinesWithoutExcluded = array_intersect($cartProductID,$excludedProducts);
    } else {
        $cartLinesWithoutExcluded = $cartProductID;
    }

    $cartLinesWithoutExcluded = count($cartLinesWithoutExcluded);
    $totalCartItems = $cartLines - $cartLinesWithoutExcluded;
    $discount = $maxCouponAmount / $totalCartItems; 
}
// here $discount is the one calculated in last loop like all previous loops didn't exists. (same thing for $cartLinesWithoutExcluded and $totalCarItems)

因为它总是只返回最后一个购物车项目的$discount。

尝试以下代码(未测试):

代码语言:javascript
复制
add_filter( 'woocommerce_coupon_get_discount_amount', 'filter_woocommerce_coupon_get_discount_amount', 10, 5 ); // add filter for all coupons
// filter to change discount if over max coupon amount
function filter_woocommerce_coupon_get_discount_amount( $discount, $discounting_amount, $cart_item, $single, $coupon ) { 
        // remove loop on applied coupons because you are managing coupon that is currently applied to the cart   
        if ( $coupon->is_type( 'percent' ) ) {
            $maxCouponAmount = get_post_meta( $coupon->get_id(), '_max_discount', true );

            // TRY TO REMOVE THIS FOR TESTING
            // OR TRY TO return $maxCouponAmount to check this value
            if ( empty( $maxCouponAmount ) ) { // do not change coupon discount if no max_discount
                return $discount;
            }
            // ---

            $excludedProducts = explode(",", get_post_meta( $coupon->get_id(), 'exclude_product_ids', true ));
            $cartLines = count(WC()->cart->get_cart());
            $cartLineItems = WC()->cart->get_cart();

            // Changes in your loop
            $cartLinesWithoutExcluded = 0; // *** UPDATE HERE

            foreach ($cartLineItems as $cartItem){
                $cartProductID[] = $cartItem['product_id'];
                if (!empty($excludedProducts)) {
                    $cartLinesWithoutExcluded += count ( array_intersect($cartProductID,$excludedProducts) );
                } else {
                    $cartLinesWithoutExcluded += count ( $cartProductID );
                }
            }
            $totalCartItems = $cartLines - $cartLinesWithoutExcluded;
            $discount = $totalCartItems > 0 ? $maxCouponAmount / $totalCartItems : 0; // Never divide by 0 !
            // end of changes in your loop
        } elseif ( $coupon->is_type( 'fixed_cart' ) ) {
            $discount = 0.00;
        }

        return $discount;

}

// apply the coupon whether it is max discount or a product price adjustment
function apply_max_amount_or_product_price_adjustment(){

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

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
    return;

    if ( !is_admin() && !wp_is_json_request() ) {
        global $wp, $woocommerce;
        $cartCoupons = WC()->cart->get_applied_coupons();
        foreach ($cartCoupons as $key => $appliedCoupon) {
            $coupon = new WC_Coupon($appliedCoupon);
            $maxCouponAmount = get_post_meta( $coupon->get_id(), '_max_discount', true );
            $excludedProducts = explode(",", get_post_meta( $coupon->get_id(), 'exclude_product_ids', true ));
            $couponType = get_post_meta( $coupon->get_id(), 'discount_type', true );
            // $fixedProductPrice = get_post_meta( $coupon->get_id(), '_adjust_price', true );
            $couponAmount = WC()->cart->get_coupon_discount_amount( $appliedCoupon );

            // removed adding filter here

            if ($couponType == 'fixed_cart'){
                $cart = WC()->cart->get_cart();
                $couponProducts = explode(',',get_post_meta( $coupon->get_id(), 'product_ids', true ));
                $fixedPricePerProduct = get_post_meta( $coupon->get_id(), '_price_per_product_amt', true );

                foreach( $cart as $cart_item ) {
                    if (in_array($cart_item['data']->get_parent_id(), $couponProducts)) {
                        $cart_item['data']->set_price( $fixedPricePerProduct );
                    }
                }
            }
        }
    }
}
add_action('woocommerce_before_calculate_totals', 'apply_max_amount_or_product_price_adjustment', 10, 1);

如有必要,请测试和编辑代码。对不起,如果我的解释似乎混乱,我是在半夜写作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70313775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档