Search code examples
phpwordpresswoocommercehook-woocommercewoocommerce-rest-api

WooCommerce add_to_cart() FAILS if cart is NOT empty


I have a fairly simple function that gets several products data and bulk-adds those products to the cart via a foreach loop. The problem is that, if the cart already contains any product added, the first product in my loop is skipped and not added. Any other products after the first one, get added no problem. If the cart IS empty, all products get added no problem, including the first one.

I have recreated the problem using a clean installation. I have only WooCommerce and Code Snippets activated. You can see the behaviour at this /sample-page/ clicking the "Add All to Cart" button. It will work for the first time, but if you reload and click again, the problem will appear.

add_shortcode( 'add-all-to-cart', 'add_all_to_cart_shortcode' );

function add_all_to_cart_shortcode() {
    global $woocommerce;
    ob_start();
    ?>
        <form id="add-all-to-cart" method="post">
        <button type="submit" name="add-all-to-cart-button" class="add-all button alt">Add all to cart</button>
        </form>
    <?php
    return ob_get_clean();
}

add_action( 'init', 'add_all_to_cart_handler' );
function add_all_to_cart_handler() {
    global $woocommerce;
    if ( isset( $_POST['add-all-to-cart-button'] ) ) {
        $products_data = array(
            array(
                'product_id' => 18,
                'variation_id' => 19,
                'quantity' => 1
            ),
            array(
                'product_id' => 21,
                'variation_id' => 22,
                'quantity' => 1
            ),
            array(
                'product_id' => 24,
                'variation_id' => 26,
                'quantity' => 1
            )
        );

        foreach ( $products_data as $product ) {
            $product_id = $product['product_id'];
            $variation_id = $product['variation_id'];
            $quantity = $product['quantity'];
            WC()->cart->add_to_cart( $product_id, $quantity, $variation_id );
        }
        wp_safe_redirect( wc_get_cart_url() );
        exit();
    }
}

What I've tried:

I've dumped all variables and all data is good, all integers. I tried checking the cart_item_key and it is being correctly assigned. I tried changing the code to first look for any given product already in cart and just update their quantity, but that did not solved the problem. Also tried throwing some WC()->cart->maybe_set_cart_cookies(); statements in there, but to no luck.

Searching for answers I found some people talking about cart sessions and the persistent cart. But I am unsure if this is related.

Thanks in advance!


Solution

  • Init hook is called way to earlier and missed the actual job in your code.

    Replace init hook with template_redirect hook when you call add_all_to_cart_handler function.