WooCommerce - Treat cart items separate if quantit

2020-03-24 08:08发布

问题:

I'm trying to do the following:

A customer adds a product with quantity "1" to the cart (the quantity field has been removed on the single product pages so only 1 can be added).

If the same product with the same variations gets added again, instead of increasing the quantity to "2", it adds it as a separate product.

I managed to do the above with the filter below, which I found on the WordPress forums.

add_filter('woocommerce_add_cart_item_data', 'force_separate_item_add', 10, 2);
function force_separate_item_add($cart_item_data, $product_id) {

    $unique_cart_item_key = md5(microtime().rand()."Hi Mom!");
    $cart_item_data['unique_key'] = $unique_cart_item_key;

    return $cart_item_data;
}

The guy's explanation was quite good, and I get it: "When an item gets added to the cart, a 'key' for that individual item in the cart is created based on the item being added and its associated meta data. If the item and its meta data are identical to another item in the cart, then the generated key will be identical too, and the the quantity of the item already in the cart will simply be incremented by the quantity being added".

The code above simply adds a new key and the cart then treats them as separate entries.

What I'm trying to do now is to find the appropriate filter for this when the quantity gets changed through the cart. So if the customer changes the quantity to "2" it will generate a new key for the "2nd" item and treat it individually.

I have tried almost every "cart" related filter I could find, searching on the WooCommerce docs, doing a mass find on Sublime on the woocommerce plugin folder for "update cart", "cart", etc, but I'm afraid I'm not really sure which on to use. The one I have worked on the most is this one:

add_action('woocommerce_before_calculate_totals', 'change_cart_item_price');
function change_cart_item_price($cart_object) {

    global $woocommerce;

    foreach ($woocommerce->cart->cart_contents as $cart_key => $cart_item_array) {        
        if($cart_item_array['quantity'] > 1 ) {
            $cart_item_key = md5(microtime().rand()."Hi Mom!");
            $cart_item_data['unique_key'] = $cart_item_key;

            $woocommerce->cart->set_quantity($cart_item_key, '1');
        }
   }

   return $cart_object;
}

Here I'm running through the cart object, checking if the quantity is bigger than one and if it is I assign a new key. I really don't know if I'm doing the right thing.

回答1:

Your woocommerce_add_cart_item_data filter was a great start for me. I ended up leaving that as-is and moving to the woocommerce_add_to_cart hook to manually process.

This is a slim version of what is currently working for me.

/**
 * This hook runs at the end of the default add to cart processes, when you try to add an item to cart.
 * If trying to add more than item to the cart, separate them into individual cart items
 *
 * @author  Mike Hemberger <mike@bizbudding.com>
 *
 * @return  void
 */
add_action( 'woocommerce_add_to_cart', 'mai_split_multiple_quantity_products_to_separate_cart_items', 10, 6 );
function mai_split_multiple_quantity_products_to_separate_cart_items( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {

    // If product has more than 1 quantity
    if ( $quantity > 1 ) {

        // Keep the product but set its quantity to 1
        WC()->cart->set_quantity( $cart_item_key, 1 );

        // Run a loop 1 less than the total quantity
        for ( $i = 1; $i <= $quantity -1; $i++ ) {
            /**
             * Set a unique key.
             * This is what actually forces the product into its own cart line item
             */
            $cart_item_data['unique_key'] = md5( microtime() . rand() . "Hi Mom!" );

            // Add the product as a new line item with the same variations that were passed
            WC()->cart->add_to_cart( $product_id, 1, $variation_id, $variation, $cart_item_data );
        }

    }

}


回答2:

There's the filter hook woocommerce_update_cart_validation