programing

WooCommerce - 수량 변경 시 총 가격 자동 업데이트

nicescript 2023. 2. 11. 16:47
반응형

WooCommerce - 수량 변경 시 총 가격 자동 업데이트

며칠 동안 찾아봤지만 아직 답이 없어요.기본적으로 woocommerce standart "update cart" 버튼을 ajax call로 대체하려고 합니다.이 버튼은 수량이 변경되면 자동으로 총 가격이 갱신됩니다.이것은 나의 html이다.

<div class="cart_item">
    <div class="product-thumbnail">
        <a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a>
    </div>

    <div class="product-name">
        <a class="cart-page-product__title" href="http://example.com">Product1 name</a>
    </div>

    <div class="product-quantity">
        <div class="quantity">
            <input type="number" step="1"   name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/>
        </div>
    </div>

    <div class="product-subtotal"><span class="amount">2 000</span></div>
        <div class="product-remove">
            <a class="product-remove_link" href="http://example.com/?remove_item">&times;</a>
        </div>
</div>
<div class="cart_item">
    <div class="product-thumbnail">
        <a href="http://example.com"><img width="90" height="90" src="path to thumbnail"/></a>
    </div>

    <div class="product-name">
        <a class="cart-page-product__title" href="http://example.com">Product2 name</a>
    </div>

    <div class="product-quantity">
        <div class="quantity">
            <input type="number" step="1"   name="cart[some_security_key][qty]" value="1" class="input-text qty text" size="4"/>
        </div>
    </div>

    <div class="product-subtotal"><span class="amount">2 000</span></div>
        <div class="product-remove">
            <a class="product-remove_link" href="http://example.com/?remove_item">&times;</a>
        </div>
</div>

기능 중.php 합계 갱신 기능이 있습니다.

public function update_total_price() {
        check_ajax_referer( 'update_total_price', 'security' );

        if ( ! defined('WOOCOMMERCE_CART') ) {
            define( 'WOOCOMMERCE_CART', true );
        }

        $cart_updated = false;
            $cart_totals  = isset( $_POST['cart'] ) ? $_POST['cart'] : '';

            if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
                foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
                    $_product = $values['data'];

                    // Skip product if no updated quantity was posted
                    if ( ! isset( $_POST['quantity'] ) ) {
                    // if ( ! isset( $cart_totals[ $cart_item_key ]['qty'] ) ) {
                        continue;
                    }

                    // Sanitize
                    $quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );
                    // $quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', $cart_totals[ $cart_item_key ]['qty'] ) ), $cart_item_key );

                    if ( '' === $quantity || $quantity == $values['quantity'] )
                        continue;

                    // Update cart validation
                    $passed_validation  = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity );

                    // is_sold_individually
                    if ( $_product->is_sold_individually() && $quantity > 1 ) {
                        wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
                        $passed_validation = false;
                    }

                    if ( $passed_validation ) {
                        WC()->cart->set_quantity( $cart_item_key, $quantity, false );
                    }

                    $cart_updated = true;
                }
            }

            // Trigger action - let 3rd parties update the cart if they need to and update the $cart_updated variable
            $cart_updated = apply_filters( 'woocommerce_update_cart_action_cart_updated', $cart_updated );

            if ( $cart_updated ) {
                // Recalc our totals
                WC()->cart->calculate_totals();
                woocommerce_cart_totals();
                exit;
            }

    }

Jquery 코드는 다음과 같습니다.

jQuery( function( $ ) {

    // wc_cart_params is required to continue, ensure the object exists
    if ( typeof wc_cart_params === 'undefined' ) {
        return false;
    }

    // Cart price update depends on quantity
    //$( document ).on( 'click', '.quantity', function() {


    $( document ).on( 'change', '.quantity, input[type=number]', function() {
        var qty = $( this ).val();
        var currentVal  = parseFloat( qty);

        $( 'div.cart_totals' ).block({ message: null, overlayCSS: { background: '#fff url(' + wc_cart_params.ajax_loader_url + ') no-repeat center', backgroundSize: '16px 16px', opacity: 0.6 } });

        var data = {
            action: 'rf_update_total_price',
            security: rf_cart_params.rf_update_total_price_nonce,
            quantity: currentVal
        };

        $.post( rf_cart_params.ajax_url, data, function( response ) {

            $( 'div.cart_totals' ).replaceWith( response );
            $( 'body' ).trigger( 'rf_update_total_price' );

        });
        return false;
    });
});

위의 코드는 카트에 1개의 제품만 있는 경우에 유효합니다. 여기에 이미지 설명 입력

하지만 제가 다른 제품을 추가하고 그 중 하나를 수량을 변경할 때, 제 기능은 제 모든 제품에 대해 수량의 마지막 값을 사용합니다.

여기에 이미지 설명 입력

예를 들어 두 번째 이미지의 총 가격은 7000(2000*1+2500*2)이어야 하지만 9000(2000*2+2500*2)입니다.나는 아약스와 jquery를 처음 접하니 도움에 감사한다.

제품뿐만 아니라 모든 카트를 업데이트하기 때문입니다.

먼저 javascript 스크립트로 아이템 카트 해시(보안 해시가 아니라 모든 제품 변형이 포함된 제품 해시)를 전송해야 합니다.

var item_hash = $( this ).attr( 'name' ).replace(/cart\[([\w]+)\]\[qty\]/g, "$1");
var data = {
        action: 'rf_update_total_price',
        security: rf_cart_params.rf_update_total_price_nonce,
        quantity: currentVal,
        hash : item_hash 
    };

그 후, 편집이 가능합니다.function update_total_price, 심플화를 실시했습니다.

function update_total_price() {

    // Skip product if no updated quantity was posted or no hash on WC_Cart
    if( !isset( $_POST['hash'] ) || !isset( $_POST['quantity'] ) ){
        exit;
    }

    $cart_item_key = $_POST['hash'];

    if( !isset( WC()->cart->get_cart()[ $cart_item_key ] ) ){
        exit;
    }

    $values = WC()->cart->get_cart()[ $cart_item_key ];

    $_product = $values['data'];

    // Sanitize
    $quantity = apply_filters( 'woocommerce_stock_amount_cart_item', apply_filters( 'woocommerce_stock_amount', preg_replace( "/[^0-9\.]/", '', filter_var($_POST['quantity'], FILTER_SANITIZE_NUMBER_INT)) ), $cart_item_key );

    if ( '' === $quantity || $quantity == $values['quantity'] )
        exit;

    // Update cart validation
    $passed_validation  = apply_filters( 'woocommerce_update_cart_validation', true, $cart_item_key, $values, $quantity );

    // is_sold_individually
    if ( $_product->is_sold_individually() && $quantity > 1 ) {
        wc_add_notice( sprintf( __( 'You can only have 1 %s in your cart.', 'woocommerce' ), $_product->get_title() ), 'error' );
        $passed_validation = false;
    }

    if ( $passed_validation ) {
        WC()->cart->set_quantity( $cart_item_key, $quantity, false );
    }

    // Recalc our totals
    WC()->cart->calculate_totals();
    woocommerce_cart_totals();
    exit;
}

여기 이것을 실현하는 간단한 방법이 있습니다.모든 명예는 레이겔 갈라드에게 돌아간다.

// we are going to hook this on priority 31, so that it would display below add to cart button.
add_action( 'woocommerce_single_product_summary', 'woocommerce_total_product_price', 31 );
function woocommerce_total_product_price() {
    global $woocommerce, $product;
    // let's setup our divs
    echo sprintf('<div id="product_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Product Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>');
    echo sprintf('<div id="cart_total_price" style="margin-bottom:20px;display:none">%s %s</div>',__('Cart Total:','woocommerce'),'<span class="price">'.$product->get_price().'</span>');
    ?>
        <script>
            jQuery(function($){
                var price = <?php echo $product->get_price(); ?>,
                    current_cart_total = <?php echo $woocommerce->cart->cart_contents_total; ?>,
                    currency = '<?php echo get_woocommerce_currency_symbol(); ?>';

                $('[name=quantity]').change(function(){
                    if (!(this.value < 1)) {
                        var product_total = parseFloat(price * this.value),
                        cart_total = parseFloat(product_total + current_cart_total);

                        $('#product_total_price .price').html( currency + product_total.toFixed(2));
                        $('#cart_total_price .price').html( currency + cart_total.toFixed(2));
                    }
                    $('#product_total_price,#cart_total_price').toggle(!(this.value <= 1));

                });
            });
        </script>
    <?php
}

2016년 6월 출시된 WooCommerce 2.6.0 이후, WooCommerce 카트 페이지는 Update cart 버튼을 클릭한 후 Ajax를 사용하여 카트 합계를 업데이트합니다.WooCommerce 2.6.0에는 WP 4.4 이후가 필요합니다.

백엔드와 독자적인 Ajax 콜을 작성할 필요가 없습니다.Update cart 버튼에 할당된 콜을 사용할 수 있습니다.

이 기능을 바로 사용하려면 무료 플러그인을 사용할 수 있습니다. 이 플러그인은 다음과 같은 편리한 추가 옵션도 있습니다.

Ajax Cart AutoUpdate for WooCommerce

또는 하위 테마를 사용하여 다음을 수행합니다.Update cart 버튼을 숨긴 다음 enqueue 스크립트를 실행하여 카트 페이지 수량 변경 시 기본 업데이트 카트 이벤트를 트리거합니다(카트 위젯과 미니 카트 위젯 모두 사용 가능).jQuery와 종속된 템플릿 리다이렉트 후크를 사용하여 이 스크립트가 카트 페이지에만 로드되도록 합니다.

CSS에서 버튼을 숨기려면 태그 대신 class.button을 사용하여 모든 WooCommerce 버전과 호환되도록 합니다.

.button[name='update_cart'] {
    display: none!important;
}

또는 PHP 헤드스타일의 숨김 버튼:

add_action('wp_head', 'hide_update_cart_button', 20);
function hide_update_cart_button() {
    echo "<style>.button[name='update_cart']{ display: none!important;}</style>";
}

jQuery에 종속된 스크립트 큐잉:

add_action( 'template_redirect', 'auto_update_cart_totals' );
function auto_update_cart_totals() {    
    if (! is_cart() ) return; // Only if it's cart page.
    // Enqueue js file.
    add_action( 'wp_enqueue_scripts', 'my_cart_autoupdate' );           
}

function my_cart_autoupdate( ) {
    // Here goes code to hide CSS button if you decide to use PHP solution for styling.

    wp_enqueue_script( 'my-cart-autoupdate', 'path-to-js-file-its-name-and-extension', array('jquery'), '', true);
}

jQuery 코드에서 가장 중요하고 일반적으로 간과되는 것은 업데이트 지연을 설정하는 것입니다.이 예에서는 1000으로 설정되어 있습니다.플러그인은 이 값을 설정에서 변경할 수 있습니다.이 지연 시간 동안 사용자가 다시 수량을 변경하면 전체 기간으로 재설정됩니다.구현되지 않은 상태에서 증분 버튼을 클릭하여 수량을 1에서 10으로 변경하면 1이 아닌 9개의 Ajax 호출이 트리거됩니다. .js 파일에 저장합니다.

var timeout;

jQuery('div.woocommerce').on('change keyup mouseup', 'input.qty', function(){ // keyup and mouseup for Firefox support
    if (timeout != undefined) clearTimeout(timeout); //cancel previously scheduled event
    if (jQuery(this).val() == '') return; //qty empty, instead of removing item from cart, do nothing
    timeout = setTimeout(function() {
        jQuery('[name="update_cart"]').trigger('click');
    }, 1000 );
});

언급URL : https://stackoverflow.com/questions/26137156/woocommerce-auto-update-total-price-when-quantity-changed

반응형