Ajax 添加到购物车,用于 WooCommerce 单品上的简单和可变产品 [英] Ajax Add to cart for simple and variable products on WooCommerce single products

查看:27
本文介绍了Ajax 添加到购物车,用于 WooCommerce 单品上的简单和可变产品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码适用于使用 WooCommerce 将简单产品添加到购物车,但不适用于可变产品.有人可以帮我吗?因为此代码适用于最新的WC,请不要删除此问题,因为网上有很多代码根本无法使用.

我收到的错误是通知中说我应该选择一个产品选项,即使我选择了一个.

JS:

jQuery(function($) {$('form.cart').on('submit', function(e) {e.preventDefault();var form = $(this);form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });var formData = new FormData(form.context);formData.append('加入购物车', form.find('[name=add-to-cart]').val() );var $thisbutton = form.find('.single_add_to_cart_button');////Ajax 动作$.ajax({url: wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'ace_add_to_cart'),数据:表单数据,类型:'POST',过程数据:假,内容类型:假,beforeSend:函数(响应){$thisbutton.removeClass('adding').addClass('loading');},完成:功能(响应){响应 = response.responseJSON;如果(!响应){返回;}if ( response.error && response.product_url ) {window.location = response.product_url;返回;}//重定向到购物车选项如果( wc_add_to_cart_params.cart_redirect_after_add === '是' ){window.location = wc_add_to_cart_params.cart_url;返回;}//触发事件以便主题可以刷新其他区域.$( document.body ).trigger( ' added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );//删除现有通知$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();//添加新通知form.closest('.product').before(response.fragments.notices_html)form.unblock();}});});});

PHP:

/* WOOCOMMERCE AJAX 添加到购物车--------------------------------------------------- */函数 ace_ajax_add_to_cart_handler() {WC_Form_Handler::add_to_cart_action();WC_AJAX::get_refreshed_fragments();}/* 为通知添加片段.*/功能 ace_ajax_add_to_cart_add_fragments( $fragments ) {$all_notices = WC()->session->get('wc_notices', array());$notice_types = apply_filters('woocommerce_notice_types', array('error', 'success', 'notice'));ob_start();foreach ( $notice_types 作为 $notice_type ) {如果 ( wc_notice_count( $notice_type ) > 0 ) {wc_get_template( "notices/{$notice_type}.php", array('消息' =>array_filter( $all_notices[ $notice_type ] ),'通知' =>array_filter( $all_notices[ $notice_type ] ),) );}}$fragments['notices_html'] = ob_get_clean();wc_clear_notices();返回 $fragments;}add_action('wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler');add_action('wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler');remove_action('wp_loaded', array('WC_Form_Handler', 'add_to_cart_action'), 20);//移除 WC Core 添加到购物车处理程序以防止重复添加add_filter('woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments');

解决方案

简单可变产品启用Ajax添加到购物车在单个产品页面你需要一些不同的东西,构建一个自定义的 Ajax 添加到购物车功能它还处理自定义产品字段和购物车项目数据操作 (WooCommerce 默认的 Ajax 添加购物车不允许).

在 WooCommerce 版本 4.9.0 上尝试以下完全测试:

add_action( 'wp_footer', 'single_product_ajax_add_to_cart_js_script' );函数 single_product_ajax_add_to_cart_js_script() {?><脚本>(功能($){$('form.cart').on('submit', function(e) {e.preventDefault();var 形式 = $(this),mainId = form.find('.single_add_to_cart_button').val(),fData = form.serializeArray();form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });if ( mainId === '' ) {mainId = form.find('input[name="product_id"]').val();}if ( typeof wc_add_to_cart_params === 'undefined' )返回假;$.ajax({类型:'POST',url: wc_add_to_cart_params.wc_ajax_url.toString().replace('%%endpoint%%', 'custom_add_to_cart'),数据 : {'product_id': mainId,'form_data' : fData},成功:功能(响应){$(document.body).trigger(wc_fragment_refresh");$('.woocommerce-error,.woocommerce-message').remove();$('input[name="quantity"]').val(1);$('.content-area').before(response);form.unblock();//控制台日志(响应);},错误:函数(错误){form.unblock();//console.log(error);}});});})(jQuery);<?php}add_action('wc_ajax_custom_add_to_cart', 'custom_add_to_cart_handler');add_action('wc_ajax_nopriv_custom_add_to_cart', 'custom_add_to_cart_handler');函数 custom_add_to_cart_handler() {if(isset($_POST['product_id']) &&isset($_POST['form_data'])) {$product_id = $_POST['product_id'];$variation = $cart_item_data = $custom_data = array();//初始化$variation_id = 0;//初始化foreach( $_POST['form_data'] 作为 $values ) {if ( strpos( $values['name'], 'attributes_' ) !== false ) {$variation[$values['name']] = $values['value'];} elseif ( $values['name'] === '数量' ) {$quantity = $values['value'];} elseif ( $values['name'] === 'variation_id' ) {$variation_id = $values['value'];} elseif ( $values['name'] !== 'add_to_cart' ) {$custom_data[$values['name']] = esc_attr($values['value']);}}$product = wc_get_product( $variation_id ? $variation_id : $product_id );//允许将产品自定义字段添加为来自 $custom_data 附加数组变量的自定义购物车项目数据$cart_item_data = (array) apply_filters('woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity, $custom_data );//添加到购物车$cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );如果( $cart_item_key ){//加入购物车成功通知wc_add_notice( sprintf('


处理产品自定义字段和购物车项目数据操作:

这个自定义 Ajax 添加到购物车代码处理产品自定义字段,允许将它们添加为自定义购物车项目数据.

为此,我们使用 woocommerce_add_cart_item_data 在我们的自定义 Ajax 添加到购物车代码中启用的 WooCommerce 专用挂钩,允许将产品自定义字段添加为自定义购物车项目数据或即时操作购物车数据.

如果我们使用此代码添加产品自定义输入文本字段:

add_action( 'woocommerce_before_add_to_cart_button', 'product_additional_custom_fields' );函数 product_additional_custom_fields() {echo '<tbody><tr><td class="label";style="width:100px">
</br>';}

然后如果您想将字段值作为自定义购物车项目数据传递,您将使用

add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data', 10, 5 );函数 add_cart_item_custom_data( $cart_item_data, $product_id, $variation_id = 0, $quantity, $custom_data = array() ) {if ( isset($custom_data['engraving']) && !empty($custom_data['engraving']) ) {$cart_item_data['engraving'] = sanitize_text_field($custom_data['engraving']);}返回 $cart_item_data;}

您可以检查以下内容,这将显示在购物车中并结帐该自定义购物车项目数据:

add_filter( 'woocommerce_get_item_data', 'display_on_cart_and_checkout', 10, 2 );功能 display_on_cart_and_checkout( $cart_data, $cart_item ) {如果( isset($cart_item['雕刻'])){$cart_data[] = 数组(姓名"=>__(雕刻文字",woocommerce"),价值"=>$cart_item['雕刻']);}返回 $cart_data;}

代码位于活动子主题(或活动主题)的functions.php 文件中.经测试有效.


注意事项:

  • 此代码可即时运行,但建议将 jQuery 代码作为外部文件加入队列.

  • 在某些主题上,您应该将:
    $('.content-area').before(response); 替换为 $('.products').之前(响应);
    正确显示通知...

The code below is working for add to cart with WooCommerce for simple products, but not for variable products. Can someone help me out? Because this code works with the latest WC, please do not remove this question because there are lots of codes for this online that do not work at all.

The error I am getting that is says in a notice that I should choose a product option, even when I chose one.

JS:

jQuery(function($) {
        $('form.cart').on('submit', function(e) {
            e.preventDefault();

            var form = $(this);
            form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });

            var formData = new FormData(form.context);
            formData.append('add-to-cart', form.find('[name=add-to-cart]').val() );

    var $thisbutton = form.find('.single_add_to_cart_button'); //


            // Ajax action
            $.ajax({
                url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'ace_add_to_cart' ),
                data: formData,
                type: 'POST',
                processData: false,
                contentType: false,
      beforeSend: function (response) {
           $thisbutton.removeClass('added').addClass('loading');
       },
                complete: function( response ) {
                    response = response.responseJSON;

                    if ( ! response ) {
                        return;
                    }

                    if ( response.error && response.product_url ) {
                        window.location = response.product_url;
                        return;
                    }

                    // Redirect to cart option
                    if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
                        window.location = wc_add_to_cart_params.cart_url;
                        return;
                    }

                    // Trigger event so themes can refresh other areas.
                    $( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );

                    // Remove existing notices
                    $( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();

                    // Add new notices
                    form.closest('.product').before(response.fragments.notices_html)

                    form.unblock();
                }
            });
        });
    });

PHP:

/* WOOCOMMERCE AJAX ADD TO CART
--------------------------------------------------- */
function ace_ajax_add_to_cart_handler() {
  WC_Form_Handler::add_to_cart_action();
    WC_AJAX::get_refreshed_fragments();
}

/* Add fragments for notices. */
function ace_ajax_add_to_cart_add_fragments( $fragments ) {
    $all_notices  = WC()->session->get( 'wc_notices', array() );
    $notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );

    ob_start();
    foreach ( $notice_types as $notice_type ) {
        if ( wc_notice_count( $notice_type ) > 0 ) {
            wc_get_template( "notices/{$notice_type}.php", array(
                'messages' => array_filter( $all_notices[ $notice_type ] ),
        'notices' => array_filter( $all_notices[ $notice_type ] ),
            ) );
    }
    }

    $fragments['notices_html'] = ob_get_clean();
  wc_clear_notices();
    return $fragments;
}

add_action( 'wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 ); // Remove WC Core add to cart handler to prevent double-add
add_filter( 'woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments' );

解决方案

To enable Ajax add to cart for simple and variable products on Single product pages you need something different, building a custom Ajax add to cart function that handles also custom product fields and cart item data manipulation (what WooCommerce default Ajax add to cart doesn't allow).

Try the following fully tested on WooCommerce version 4.9.0:

add_action( 'wp_footer', 'single_product_ajax_add_to_cart_js_script' );
function single_product_ajax_add_to_cart_js_script() {
    ?>
    <script>
    (function($) {
        $('form.cart').on('submit', function(e) {
            e.preventDefault();

            var form   = $(this),
                mainId = form.find('.single_add_to_cart_button').val(),
                fData  = form.serializeArray();

            form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });

            if ( mainId === '' ) {
                mainId = form.find('input[name="product_id"]').val();
            }

            if ( typeof wc_add_to_cart_params === 'undefined' )
                return false;

            $.ajax({
                type: 'POST',
                url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'custom_add_to_cart' ),
                data : {
                    'product_id': mainId,
                    'form_data' : fData
                },
                success: function (response) {
                    $(document.body).trigger("wc_fragment_refresh");
                    $('.woocommerce-error,.woocommerce-message').remove();
                    $('input[name="quantity"]').val(1);
                    $('.content-area').before(response);
                    form.unblock();
                    // console.log(response);
                },
                error: function (error) {
                    form.unblock();
                    // console.log(error);
                }
            });
        });
    })(jQuery);
    </script>
    <?php
}

add_action( 'wc_ajax_custom_add_to_cart', 'custom_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_custom_add_to_cart', 'custom_add_to_cart_handler' );
function custom_add_to_cart_handler() {
    if( isset($_POST['product_id']) && isset($_POST['form_data']) ) {
        $product_id = $_POST['product_id'];

        $variation = $cart_item_data = $custom_data = array(); // Initializing
        $variation_id = 0; // Initializing

        foreach( $_POST['form_data'] as $values ) {
            if ( strpos( $values['name'], 'attributes_' ) !== false ) {
                $variation[$values['name']] = $values['value'];
            } elseif ( $values['name'] === 'quantity' ) {
                $quantity = $values['value'];
            } elseif ( $values['name'] === 'variation_id' ) {
                $variation_id = $values['value'];
            } elseif ( $values['name'] !== 'add_to_cart' ) {
                $custom_data[$values['name']] = esc_attr($values['value']);
            }
        }

        $product = wc_get_product( $variation_id ? $variation_id : $product_id );

        // Allow product custom fields to be added as custom cart item data from $custom_data additional array variable
        $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity, $custom_data );

        // Add to cart
        $cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );

        if ( $cart_item_key ) {
            // Add to cart successful notice
            wc_add_notice( sprintf(
                '<a href="%s" class="button wc-forward">%s</a> %d &times; "%s" %s' ,
                wc_get_cart_url(),
                __("View cart", "woocommerce"),
                $quantity,
                $product->get_name(),
                __("has been added to your cart", "woocommerce")
            ) );
        }

        wc_print_notices(); // Return printed notices to jQuery response.
        wp_die();
    }
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

All notices are enable and displayed on the fly:


Handling product custom fields and cart item data manipulation:

This custom Ajax add to cart code handle product custom fields, allowing to add them as custom cart item data.

For that we use woocommerce_add_cart_item_data WooCommerce dedicated hook enabled in our custom Ajax add to cart code, allowing to add product custom fields as custom cart item data or manipulate cart data on the fly.

If we add a product custom input text field with this code:

add_action( 'woocommerce_before_add_to_cart_button', 'product_additional_custom_fields' );
function product_additional_custom_fields() {
    echo '<table class="variations" cellspacing="0" width="100px">
            <tbody><tr>
                <td class="label" style="width:100px"><label for="engraving">' . __("Engraving text") . '</label></td>
                <td class="value">
                    <input type="text" name="engraving" id="engraving" value="" />
                </td>
            </tr></tbody>
    </table>
    </br>';
}

Then if you want to pass the field value as custom cart item data, you will use

add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data', 10, 5 );
function add_cart_item_custom_data( $cart_item_data, $product_id, $variation_id = 0, $quantity, $custom_data = array() ) {
    if ( isset($custom_data['engraving']) && ! empty($custom_data['engraving']) ) {
        $cart_item_data['engraving'] = sanitize_text_field($custom_data['engraving']);
    }

    return $cart_item_data;
}

And you can check with the following, that will display in cart and checkout that custom cart item data:

add_filter( 'woocommerce_get_item_data', 'display_on_cart_and_checkout', 10, 2 );
function display_on_cart_and_checkout( $cart_data, $cart_item ) {
    if ( isset($cart_item['engraving']) ) {
        $cart_data[] = array( 
            "name" => __("Engraving text", "woocommerce"),  
            "value" => $cart_item['engraving'] 
        );
    }

    return $cart_data;
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.


Notes:

  • This code works on the fly as it is, but it's recommended to enqueue the jQuery code as an external file.

  • On some themes you should replace:
    $('.content-area').before(response); with $('.products').before(response);
    to display the notices correctly…

这篇关于Ajax 添加到购物车,用于 WooCommerce 单品上的简单和可变产品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆