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