php Ajax加入购物车WooCommerce中的简单和可变产品单一产品

wlsrxk51  于 2023-10-15  发布在  PHP
关注(0)|答案(2)|浏览(124)

下面的代码适用于简单产品的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('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' );
j91ykkif

j91ykkif1#

要在单一产品页面上为简单可变产品启用Ajax添加到购物车**,您需要做一些不同的事情,构建一个自定义Ajax添加到购物车功能**,还可以处理自定义产品字段和购物车项目数据操作 (WooCommerce默认Ajax添加到购物车不允许)
尝试以下在WooCommerce 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();
    }
}

代码放在活动子主题(或活动主题)的functions.php文件中。测试和作品。
所有通知均启用并即时显示:

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

这个自定义Ajax添加到购物车代码处理产品自定义字段,允许将它们添加为自定义购物车项目数据。
为此,我们使用woocommerce_add_cart_item_data WooCommerce专用钩子在我们的自定义Ajax添加到购物车代码中启用,允许添加产品自定义字段作为自定义购物车项目数据或动态操作购物车数据。
如果我们使用以下代码添加产品自定义输入文本字段:

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>';
}

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

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;
}

你可以检查以下,这将显示在购物车和结帐,自定义购物车项目数据:

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;
}

代码放在活动子主题(或活动主题)的functions.php文件中。测试和作品。

备注:

  • 这段代码是动态工作的,但建议将jQuery代码作为外部文件入队。
  • 在某些主题上,您应该替换:

$('.content-area').before(response);$('.products').before(response);
正确显示通知

pgvzfuti

pgvzfuti2#

感谢有用的片段,但上面的代码不适用于访客使用,而仅适用于登录。wc_fragment_refresh在您注销并将其用作访客用户时不会触发。

$(document.body).trigger("wc_fragment_refresh");

问候

相关问题