phpwordpresswoocommercecartproduct-quantity

WooCommerce: Increase cart item quantity if the product already exist in cart


I want to increase the quantity of a product on the cart page of WooCommerce if the product already exists on the cart.

I tried this piece of code

if ( 'same_product_added_to_cart' === $customer_gets_as_free ) {
   foreach ( $main_product_id as $main_product_single ) {
        $main_product_single = intval( $main_product_single );
    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( $cart_item['product_id'] === $main_product_single ) {
        // Get the current quantity
        $current_quantity = $cart_item['quantity'];
        // Increase the quantity by one
        $new_quantity = $current_quantity + 1;

        // Update the cart with the new quantity
        WC()->cart->set_quantity( $cart_item_key, $new_quantity );

        break; // Exit the loop since we have found our product
       }
       }
   }
}

It did not work, instead, it triggered an infinite amount of loops giving an error. What am I doing wrong here. and also the add_to_cart() function gives an error of the same type.


Solution

  • Normally, WooCommerce does that by itself if there is no different custom cart item data added to the cart item on add to cart.

    There are mistakes and missing steps in your code.

    Here is the way to merge duplicated products (cart items):

    add_action( 'woocommerce_before_calculate_totals', 'merge_duplicated_products_in_cart');
    function merge_duplicated_products_in_cart( $cart ) {
        if ((is_admin() && !defined('DOING_AJAX')))
            return;
    
        if (did_action('woocommerce_before_calculate_totals') >= 2)
            return;
    
        $items_data = $item_update = []; // initializing
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            $product_id = $cart_item['data']->get_id();
            $quantity   = $cart_item['quantity'];
    
            // Check if the product exists
            if( in_array($product_id, array_keys($items_data)) ) {
                // Same product found
                $item_update['item_qty'] = $items_data[$product_id]['qty'] + $quantity; // Set cumulated quantities
                $item_update['item_key'] = $items_data[$product_id]['key']; // Add first product item key
                $item_update['item_remove'] = $cart_item_key; // Add current item key (product to be removed)
                break; // Stop the loop
            } 
            // Add product_id, cart item key and item quantity to the array (for each item)
            else {
                $items_data[$product_id] = array(
                    'key' => $cart_item_key,
                    'qty' => $quantity
                );
            }
        }
        unset($items_data); // delete the variable
    
        if ( ! empty($item_update) ) {
            $cart->remove_cart_item($item_update['item_remove']); // remove last item (same product)
            $cart->set_quantity($item_update['item_key'], $item_update['item_qty']); // Update quantity on first item(same product)
            unset($item_update); // delete the variable
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.


    Addition (based on the OP comment):

    The following will target specific defined product(s). If a specific product is already in cart, increase the quantity by one (define your product(s) ID(s) below):

    add_action( 'woocommerce_before_calculate_totals', 'merge_duplicated_products_in_cart');
    function merge_duplicated_products_in_cart( $cart ) {
        if ((is_admin() && !defined('DOING_AJAX')))
            return;
    
        if (did_action('woocommerce_before_calculate_totals') >= 2)
            return;
    
        $targeted_product_ids = array(18); // <== HERE set your(s) targeted product(s) ID(s)
    
        $items_data = $item_update = []; // initializing
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
            $product_id = $cart_item['data']->get_id();
    
            // Look for specific products only
            if ( in_array($product_id, $targeted_product_ids) ) {
                $quantity   = $cart_item['quantity'];
    
                // Check if the product is already in cart
                if( in_array($product_id, array_keys($items_data)) ) {
                    // Same product found
                    $item_update['item_qty'] = $items_data[$product_id]['qty'] + 1; // ADD ONE TO THE QUANTITY
                    $item_update['item_key'] = $items_data[$product_id]['key']; // Add first product item key
                    $item_update['item_remove'] = $cart_item_key; // Add current item key (product to be removed)
                    break; // Stop the loop
                } 
                // Add product_id, cart item key and item quantity to the array (for SPECIFIC items only)
                else {
                    $items_data[$product_id] = array(
                        'key' => $cart_item_key,
                        'qty' => $quantity
                    );
                }
            }
        }
        unset($items_data); // delete the variable
    
        if ( ! empty($item_update) ) {
            $cart->remove_cart_item($item_update['item_remove']); // remove last item (same product)
            $cart->set_quantity($item_update['item_key'], $item_update['item_qty']); // Update quantity on first item(same product)
            unset($item_update); // delete the variable
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.