通过AJAX添加自定义购物车项目数据添加到购物车

时间:2018-07-03 作者:Edmund Chan

我正在使用这个插件——Woocommerce PDF代金券——它非常好用。但是,在将我的主题的“添加到购物车”自定义到AJAXm之后,它不会在迷你购物车和购物车页面中显示自定义数据。如果我恢复到默认的add-to-cart,效果会很好,但是我的AJAX回调肯定有smth错误。这就是我正在使用的:

// JS
$add_to_cart.on(‘click’, function(e) {
    e.preventDefault();
    var var_id = $(this).siblings(‘.variation_id’).val();
    var prod_id = $(this).siblings(‘input[name=“product_id”]‘).val();
    var item = {};
    var $variation_form = $( this ).closest( ‘.variations_form’ );
    var variations = $variation_form.find( ‘select[name^=attribute]’ );
    var mini_cart = $(‘.mini-cart-menu-item’);
    var mini_cart_contents = $(‘.widget_shopping_cart’);
    var url = ajax_obj.ajax_url;
    var data = {
        action: ‘nerb_ajax_add_to_cart_woo’,
        ‘product_id’: prod_id,
        ‘variation_id’: var_id,
        ‘variation’: item
    }

    variations.each( function()  {
        var $this = $(this);
        attributeName = $this.attr( ‘name’ );
        attributevalue = $this.val();
        item[attributeName] = attributevalue;
    });

    $.post( url, data, function(response) {         
        if (response) {
            mini_cart.html(response.fragments[\'a.cart-contents\']);
            mini_cart_contents.html(
             response.fragments[\'div.widget_shopping_cart_content\']
            );
        }       
    });
})

//PHP AJAX Callback
function nerb_ajax_add_to_cart_woo() {
    $product_id = apply_filters( \'woocommerce_add_to_cart_product_id\', absint( $_POST[\'product_id\'] ) );
    $product = wc_get_product( $product_id );
    $quantity = empty( $_POST[\'quantity\'] ) ? 1 : apply_filters( \'woocommerce_stock_amount\', $_POST[\'quantity\'] );
    $variation_id = $_POST[\'variation_id\'];
    $variations  = $_POST[\'variation\'];
    $passed_validation = apply_filters( \'woocommerce_add_to_cart_validation\', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data );

    if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) ) {
        do_action( \'woocommerce_ajax_added_to_cart\', $product_id );
        if ( get_option( \'woocommerce_cart_redirect_after_add\' ) == \'yes\' ) {
            wc_add_to_cart_message( $product_id );
        }
        // Return fragments
        WC_AJAX::get_refreshed_fragments();
    } 
    die();  
}

add_action( \'wp_ajax_nerb_ajax_add_to_cart_woo\', \'nerb_ajax_add_to_cart_woo\' );
add_action( \'wp_ajax_nopriv_nerb_ajax_add_to_cart_woo\', \'nerb_ajax_add_to_cart_woo\' );
我相信这与JS函数中的“var item={}”有关。我想我可以选择自定义字段并将值赋给变量,但我认为如果我将来添加新的自定义字段,那么必须再次这样做是没有意义的。所以我不确定要为“var item”分配什么值

1 个回复
SO网友:elmediano

我也有同样的问题,只是碰巧找到了一种方法——可能不是最好的,但目前还有效。

以下是我在不使用任何AJAX的情况下,了解如何在幕后完成的步骤:

我先得甩了$_POSTwoocommerce_add_to_cart_validation 钩子以查看插件如何发送数据。它是这样做的:

[recipient_name] => Array
(
    [12345] => 
    [67890] => John Smith
)

[recipient_email] => Array
(
    [12345] => 
    [67890] => [email protected]
)

[message] => Array
(
    [12345] => 
    [67890] => Enjoy your voucher!
)
数字键是变体ID。

然后我转储了购物车数据,查看它是如何保存到购物车的:

add_action( \'woocommerce_after_cart\', \'but_whats_in_the_cart\' );
function but_whats_in_the_cart() {
    $cart = WC()->cart->get_cart();
    echo \'<pre>\';
    print_r($cart);
    echo \'</pre>\';
}
它给了我这个:

Array
    (
    [825d53934cc8498d59e3e553a5afa896] => Array
    (
        [voucher_template_id] => 27
        [voucher_image_id] => 378932
        [voucher_random] => voucher_5bc8babc5dee6
        [voucher_item_meta_data] => Array
        (
            [recipient_name] => John Smith
            [recipient_email] => [email protected]
            [message] => Enjoy your voucher!
        )
... array continues.
所以在我的AJAX调用中,我确保发送了这三段数据,然后格式化并将它们放入一个带有键的数组中[voucher_item_meta_data].

我正在构建的网站上的整个“添加到购物车”部分非常具体,因为我没有显示标准WooCommerce样式的变化(在选择的元素中),而是将它们放在一个列表中,用户只需检查他们想要的变化、数量,然后立即将它们全部添加到购物车中。我传递的所有数据都是数据属性,PDF凭证表单是自定义的。Basically, I\'m not using the WooCommerce add to cart form at all.

但在您的示例中,您需要获取PDF凭证表单数据并通过AJAX发送,可能是这样的?

var recipient_name = $(\'#selector_for_name\').val();
var recipient_email = $(\'#selector_for_email\').val();
var message = $(\'#selector_for_message\').val();
那么,WP-AJAX是一个棘手的问题。我找不到一个“;“正确”;通过AJAX将数据传递到购物车的方法。NOT 产品的数据,但每个购物车密钥的购物车数据。

我找到了一些关于必须循环使用购物车键并以这种方式添加数据的帖子,所以我尝试了一下,它成功了。

因此,在如上所述传递表单数据后,您可以执行以下操作:

function nerb_ajax_add_to_cart_woo() {
// declare global
global $woocommerce;

$product_id = apply_filters( \'woocommerce_add_to_cart_product_id\', absint( $_POST[\'product_id\'] ) );
$product = wc_get_product( $product_id );
$quantity = empty( $_POST[\'quantity\'] ) ? 1 : apply_filters( \'woocommerce_stock_amount\', $_POST[\'quantity\'] );
$variation_id = $_POST[\'variation_id\'];
$variations  = $_POST[\'variation\'];
$passed_validation = apply_filters( \'woocommerce_add_to_cart_validation\', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data );

// pdf voucher form data
$pdf_form_data[\'recipient_name\'] = $_POST[\'recipient_name\'];
$pdf_form_data[\'recipient_email\'] = $_POST[\'recipient_email\'];
$pdf_form_data[\'message\'] = $_POST[\'message\'];

if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) ) {
    do_action( \'woocommerce_ajax_added_to_cart\', $product_id );

    /* HERE IS THE BIT THAT DOES THE TRICK */
    // you need to cycle the cart replace the meta of the correspondant key
    $cart = $woocommerce->cart->cart_contents;
    foreach ($cart as $key => $item) {
        // check if voucher meta already exists for an item, and if so, skip
        if($item[\'voucher_item_meta_data\']) {
            continue;
        } else {
          // make sure we only add voucher data to the variation just added and only if data isn\'t there already so we don\'t override previously added ones
            if( $item[\'variation_id\'] === $variation_id && !isset($item[\'voucher_item_meta_data\']) ) {
                $woocommerce->cart->cart_contents[$key][\'voucher_item_meta_data\'] = $pdf_form_data;
            }
        }
    }

    // This is the magic: With this function, the modified object gets saved.
    $woocommerce->cart->set_session();

    
    if ( get_option( \'woocommerce_cart_redirect_after_add\' ) == \'yes\' ) {
        wc_add_to_cart_message( $product_id );
    }
    // Return fragments
    WC_AJAX::get_refreshed_fragments();
} 
die();  
}

add_action( \'wp_ajax_nerb_ajax_add_to_cart_woo\', \'nerb_ajax_add_to_cart_woo\' );
add_action( \'wp_ajax_nopriv_nerb_ajax_add_to_cart_woo\', \'nerb_ajax_add_to_cart_woo\' );
I have not tested this code 以你目前的设置,但这或多或少是我所做的,它对我起到了作用。

更新-2018年10月19日,我发现了一个bug,并更新了上面的PHP代码。由于我们首先添加产品,然后将凭证元数据添加到购物车中,因此在添加第二个产品时,代码将第一个产品的凭证元数据替换为第二个产品的凭证元数据(依此类推)。所以我们只需要检查数组键voucher_item_meta_data 如果存在,请跳过它:

// check if voucher meta already exists for an item, and if so, skip
if($item[\'voucher_item_meta_data\']) {
    continue;
} else {
    // make sure we only add voucher data to the variation just added and only if data isn\'t there already so we don\'t override previously added ones
    if( $item[\'variation_id\'] === $variation_id && !isset($item[\'voucher_item_meta_data\']) ) {
        $woocommerce->cart->cart_contents[$key][\'voucher_item_meta_data\'] = $cart_item_data;
    }
}

结束

相关推荐