Access our premium support and let us know your problems, we will help you solve them.

0
No products in the cart.

Forum Replies Created

Viewing 1 post (of 1 total)
  • Author
    Posts
  • in reply to: How to update cart item meta – woocommerce #10196
    blankphong-tran
    Participant

    I’m newbie and my English is not good so the answer may be a little confusing.

    Thank vlad274 for the advice.

    My approach:

    Same with Daniel Salcedo, I also try to change the metadata by editing woocommerce_sessions, but there is a problem. When adding an item to the cart, the woocommerce will create a unique cart_item_key for it by md5 (product_id + … + metadata), then look for this cart_item_key already exists, if available, this item will be updated in quantity, otherwise will create a new item.

    This means that if you change the meta value of the hat product from blue to red, then add the hat product with blue, instead of creating a new item blue hat, it will only increase the quantity of red hat, you need to change the cart_item_key if you want the cart to be updated correctly.

    Changing cart_item_key is quite risky, instead we can simply remove and re-add the product. Like this

    // get cart_item_key of item you want to change
    $cart_item_key_old = $_POST['cart_item_key']; 
    
    // retrieve its information
    $cart_item_old = WC()->cart->cart_contents[ $cart_item_key_old ];
    $product_id_old = $cart_item_old['product_id'];
    $quantity_old = $cart_item_old['quantity'];
    $variation_id_old = $cart_item_old['variation_id'];
    $variation_old = $cart_item_old['variation'];
    
    // creating a cart_item_key with the same information except metadata
    $cart_item_key_new = WC()->cart->generate_cart_id( $product_id_old, $variation_id_old, $variation_old, ['color'=>'red'] );
    // check new cart_item_key already exists
    $found = WC()->cart->find_product_in_cart( $cart_item_key_new );
    
    // if true, update its quantity
    if ($found != '') {
        $new_quantity = $cart_item_old['quantity'] + WC()->cart->cart_contents[ $cart_item_key_new ]['quantity'];
        WC()->cart->set_quantity( $cart_item_key_new, $new_quantity );
    }
    // else, re-add with new metadata
    else {
        WC()->cart->add_to_cart($product_id_old, $quantity_old, $variation_id_old, $variation_old, ['color'=>'red'] );
    }
    
    // finally delete the old item
    WC()->cart->remove_cart_item($cart_item_key_old);
    
    wp_die();
    

    Note: If you want to submit cart form instead of page refreshes after running the above ajax, the quantity of item is likely to be overridden by the set_quantity method when woocommerce update_cart. In this case you just need to return new_quantity and change the input value by js before submitting the form.

    Full code:

    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        ...
        ?>
        <!-- place it anywhere within the foreach -->
        <div class="box-type-field">
            <select class="box-type" name="box-type" cart_item_key="<?php echo $cart_item_key ?>">
                <option <?php echo $cart_item['box-type']=='boxes'?"selected":""; ?> value="boxes"><?php _e( 'Boxes', 'woocommerce' ); ?></option>
                <option <?php echo $cart_item['box-type']=='bags'?"selected":""; ?> value="bags"><?php _e( 'Bags', 'woocommerce' ); ?></option>
            </select>
        </div>
        <?php
        ...
    }
    

    AJAX:

    $('.box-type-field .box-type').live('change', function () {
        var cartItemKey = $(this).attr("cart_item_key");
        var boxType = $(this).val();
        $.ajax({
            type : "post", 
            url : '<?php echo admin_url('admin-ajax.php');?>',
            datatype: 'json',
            data : {
                action : "update_cart_boxtype",
                cart_item_key : cartItemKey,
                box_type : boxType,
            },
            success: function(cartItem) {
                cartItemKey = cartItem[0];
                cartItemQty = cartItem[1];
                if (cartItem) $('input[name="cart['+cartItemKey+'][qty]"]').val(cartItemQty); // update quantity 
    
                $('.woocommerce-cart-form button[type="submit"]').click(); // submit form
            }
        })
    })
    

    PHP:

    add_action( 'wp_ajax_update_cart_boxtype', 'update_cart_boxtype_init' );
    add_action( 'wp_ajax_nopriv_update_cart_boxtype', 'update_cart_boxtype_init' );
    function update_cart_boxtype_init() {
        if ( ! WC()->cart->is_empty() ) {
            $cart_item_key = (isset($_POST['cart_item_key']))?$_POST['cart_item_key'] : '';
            $cart_item = WC()->cart->cart_contents[ $cart_item_key ];
            $box_type = (isset($_POST['box_type']))?$_POST['box_type'] : '';
            $cart_updated = false;
    
            $cart_item_key_new = WC()->cart->generate_cart_id( $cart_item['product_id'], $cart_item['variation_id'], $cart_item['variation'], ['box-type'=>$box_type] );
    
            $found = WC()->cart->find_product_in_cart( $cart_item_key_new );
    
            if ($found != '') {
                $new_qty = $cart_item['quantity'] + WC()->cart->cart_contents[ $cart_item_key_new ]['quantity'];
                WC()->cart->remove_cart_item($cart_item_key);
                wp_send_json_success([$cart_item_key_new, $new_qty]);
            } else {
                WC()->cart->add_to_cart($cart_item['product_id'], $cart_item['quantity'], $cart_item['variation_id'], $cart_item['variation'], ['box-type' => $box_type]);
                $cart_updated = true;
                WC()->cart->remove_cart_item($cart_item_key);
                wp_send_json_success(false);
            }
        }
        wp_die();
    }
    
Viewing 1 post (of 1 total)