php - Make specific products mutually exclusive in WooCommerce
one text
Solution:
There is a much simpler way using Add to cart validation hook this way:
add_filter( 'woocommerce_add_to_cart_validation', 'wc_add_to_cart_validation_filter_callback', 10, 3 );
function wc_add_to_cart_validation_filter_callback( $passed, $product_id, $quantity ) {
if( WC()->cart->is_empty() )
return $passed;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
if( ( $product_id = $product_id1 && $cart_item['product_id'] == $product_id2 )
|| ( $product_id = $product_id2 && $cart_item['product_id'] == $product_id1 ) ) {
wc_add_notice( sprintf(
__("This product can't not be purchased toggether with %s."),
'"<strong>' . $cart_item['data']->get_name() . '</strong>"'
), 'error' );
return false;
}
}
return $passed;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Addition (related to your comment):
Another way is to remove the first item silently when both products are in cart:
add_action('woocommerce_before_calculate_totals', 'keep_last_variation_from_variable_products', 10, 1 );
function keep_last_variation_from_variable_products( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$product_id1 = 37; // Single product Id
$product_id2 = 19; // Variable product Id
$product_ids = array($product_id1, $product_id2);
$items_keys = array();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// If cart item matches with one of our defined product
if ( in_array( $cart_item['product_id'], $product_ids ) ) {
// Set the cart item key in an array (avoiding duplicates)
$items_keys[$cart_item['product_id']] = $cart_item_key;
}
}
// If both products are in cart just keep the last one silently
if( count($items_keys) > 1 ) {
$cart->remove_cart_item( reset($items_keys) ); // remove the first one
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Source