WooCommerce-如何使用具有相同购物车按钮的Ajax将多种不同的产品添加到购物车?

时间:2019-08-31 18:16:25

标签: php jquery ajax wordpress woocommerce

我正在尝试使用Ajax,只需单击一下按钮即可将多个不同的产品添加到购物车中。 AddToCart-Button位于非WooCommerce页面模板中。

我认为可以通过等待第一个ajax发布成功,然后迭代到下一个产品等等来解决,直到所有选定的产品都完成了ajax发布,此后才应该成功。

我只是不知道该怎么做:)你也许知道如何做吗?

这是我的产品,格式为html:

<form id="buy-tickets" action="https://mydomain.de/cart/" class="cart" method="post" enctype="multipart/form-data" novalidate="">
<input type="hidden" name="product_id[]" value="5353"><div class="terminMain"><div class="terminDate">28.09.2019 Event Name 1<p><b>(Noch Plätze frei)</b></p></div><div class="personenNumber" id="personenNumber1">
                        <div class="inputField">
                            <input type="button" value="-" class="qtyminus" field="quantity_5353" id="qtyminus1">
                            <input type="text" id="quantity_5353" name="quantity_5353" value="0" class="qty">
                            <input type="button" value="+" class="qtyplus" field="quantity_5353" id="qtyplus1">
                            <input type="hidden" name="stock" value="1985" field="stock">
                        </div>
                    </div></div><input type="hidden" name="product_id[]" value="5354"><div class="terminMain"><div class="terminDate">31.03.2026 Event Name 2<p><b>(Noch Plätze frei)</b></p></div><div class="personenNumber" id="personenNumber2">
                        <div class="inputField">
                            <input type="button" value="-" class="qtyminus" field="quantity_5354" id="qtyminus2">
                            <input type="text" id="quantity_5354" name="quantity_5354" value="0" class="qty">
                            <input type="button" value="+" class="qtyplus" field="quantity_5354" id="qtyplus2">
                            <input type="hidden" name="stock" value="1989" field="stock">
                        </div>
                    </div></div>            <div class="buchenBtn">
                <div class="btns woocommerce add-to-cart"> 
                            <button type="submit" name="ticket_process" value="1" class="ajax_add_to_cart single_add_to_cart_button btn added" id="buchen-wootickets">Buchen</button> <a href="https://mydomain.de/cart/" class="added_to_cart wc-forward" title="Warenkorb anzeigen">Show Cart</a>

                </div>
            </div>
</form>

这是jQuery:

(function ($) {
    $( document ).on( 'click', '.single_add_to_cart_button', function(e) {
        e.preventDefault();
        var tickets = $('#buy-tickets input[name="product_id[]"]');
        var ticketsData = [];
        var $this, ticketId, ticketQty, ticketProd;  
        tickets.each(function() {
                    $this = $( this );
                    id = $this.val();
                    ticketQty = $('#quantity_'+id).val();
                    if(ticketQty > 0){
                        ticketProd = {
                            action: 'woocommerce_ajax_add_to_cart', 
                            product_id: id, 
                            product_sku: '',
                            quantity: ticketQty,
                            variation_id: 0,
                        };
                        ticketsData.push(ticketProd);
                    }   
            });
        console.log('tickets: ', ticketsData);

        var $thisform = $('#buy-tickets');
        var $thisbutton = $(this);

        $.each(ticketsData, function(index, value){
            $.each(this, function (index, value) {
                console.log(index + " :: " + value);
            });
            $(document.body).trigger('adding_to_cart', [$thisbutton, this]);

            $.ajax({
                type: 'post',
                url: wc_add_to_cart_params.ajax_url,
                data: this,
                beforeSend: function (response) {
                    $thisform.addClass('loading');
                    $thisbutton.removeClass('added');
                },
                complete: function (response) {
                    $thisform.removeClass('loading');
                    $thisbutton.addClass('added');
                },
                success: function (response) {

                    if (response.error & response.product_url) {
                        window.location = response.product_url;
                        return;
                    } else {
                        $(document.body).trigger('added_to_cart', [response.fragments, response.cart_hash, $thisbutton]);
                    }
                },
            });

            return false;

        });
    });
})(jQuery);

还有处理我的Ajax的php函数:

add_action( 'wp_ajax_woocommerce_ajax_add_to_cart', 'tec_woocommerce_ajax_add_to_cart' );
add_action( 'wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'tec_woocommerce_ajax_add_to_cart' );

function tec_woocommerce_ajax_add_to_cart() {

            $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
            $quantity          = empty( $_POST['quantity'] ) ? 1 : wc_stock_amount( $_POST['quantity'] );
            $variation_id      = absint( $_POST['variation_id'] );
            $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
            $product_status    = get_post_status( $product_id );

    if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id ) && 'publish' === $product_status ) {

        do_action( 'woocommerce_ajax_added_to_cart', $product_id );

        if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
            wc_add_to_cart_message( array( $product_id => $quantity ), true );
        }

        WC_AJAX::get_refreshed_fragments();
    } else {

        $data = array(
            'error'       => true,
            'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ),
        );

        echo wp_send_json( $data );
    }

            wp_die();
}

该代码已经可以正常工作了,只是罪魁祸首:它仅向购物车添加了1个产品ID及其设置的数量,然后停止,即使同时通过设置其他产品的数量选择了一个以上的产品。 / p>

我正在寻找一种解决方案,该解决方案将根据每种产品设置的数量将所有选择的产品添加到购物车中。

有帮助吗?建议?

1 个答案:

答案 0 :(得分:0)

以下代码已添加到我的functions.php中。它显示了如何在单个AJAX请求中将多个产品发送到WooCommerce。这只是一个骨架,您将需要添加实际上将产品添加到购物车的PHP代码。

add_action( 'woocommerce_after_main_content', function() {
?>
<button id="saskia-add_multiple_products" style="background-color: cyan; border: 3px solid red; margin:50px;">
    Add Multiple Products
</button>
<script>
    jQuery( 'button#saskia-add_multiple_products' ).click( function() {
        var productsToAdd = [
            { id: 2650, quantity: 1 },
            { id: 3060, quantity: 2 }
        ];
        // There are multiple ways of sending complex data from JavaScript to WordPress
        // JavaScript: JSON.stringify(), jQuery: .serialize() or the following bare-bones
        // way which is wordy but probably the easiest to understand. Since, your data
        // is already in a HTML form .serialize() is probably the best but I am too lazy
        // to make a form so I am testing from data in a JavaScript array.
        var data = { action: 'saskia_add_multiple_products', id: [], quantity: [] };
        jQuery.each(productsToAdd, function( index, value ) {
            data.id[index]       = value.id;
            data.quantity[index] = value.quantity;
        } );
        jQuery.post( 'http://localhost/wp-admin/admin-ajax.php', data, function(data){ /* process success response */} );
    } );
</script>
<?php
} );

add_action( 'wp_ajax_saskia_add_multiple_products', function() {
    error_log( 'ACTION:wp_ajax_nopriv_saskia_add_multiple_products:$_POST=' . print_r( $_POST, TRUE ) );
    for ( $i = 0; $i < count( $_POST['id'] ); $i++ ) {
        $product_id = $_POST['id'][$i];
        $quantity   = $_POST['quantity'][$i];
        error_log( 'ACTION:wp_ajax_nopriv_saskia_add_multiple_products:$product_id=' . $product_id );
        error_log( 'ACTION:wp_ajax_nopriv_saskia_add_multiple_products:$quantity='   . $quantity );
        /* add each individual product to cart */
    }
    // return the update cart HTML fragments
    WC_AJAX::get_refreshed_fragments();
} );

此HTTP请求的$ _POST是:

$_POST=Array
(
    [action] => saskia_add_multiple_products
    [id] => Array
        (
            [0] => 2650
            [1] => 3060
        )

    [quantity] => Array
        (
            [0] => 1
            [1] => 2
        )

)

您可能想在表单上尝试jQuery的.serialize()。我认为这将是最简洁的解决方案。如果还不够,请通知我。现在,我已经激活了WooCommerce,可以轻松地向此答案添加更多详细信息。

添加

我在HTML表单上尝试了jQuery的.serialize()。首先,您必须添加一个隐藏的HTML <input>元素以提供AJAX操作参数:

<form id="buy-tickets" action="https://mydomain.de/cart/" class="cart" method="post" enctype="multipart/form-data" novalidate="">
    <input type="hidden" name="action" value="saskia_add_multiple_products" />
    ...
</form>

使用.serialize()的jQuery AJAX调用是:

jQuery.post( 'http://localhost/wp-admin/admin-ajax.php',
    jQuery('form#buy-tickets').serialize(),
    function(data) { /* process success response */}
);

这将发送以下$ _POST:

$_POST=Array
(
    [action] => saskia_add_multiple_products
    [product_id] => Array
        (
            [0] => 5353
            [1] => 5354
        )

    [quantity_5353] => 0
    [stock] => 1989
    [quantity_5354] => 0
)

我不太了解其中的一些内容,但是我认为,如果您对表格进行调整,则可以使用jQuery的.serialize()来批量处理产品。考虑更改

name="quantity_5353" -> name="quantity[]"
name="quantity_5354" -> name="quantity[]"

我认为您不需要发送“库存”。我也不会将产品数据直接硬编码到表单中,而是使用PHP变量,以便可以将表单再次用于其他产品。理想情况下,表单中产品的HTML应该使用foreach($ products as $ product){...}生成,以便表单可以用于任意数量的产品,而不仅仅是2种。