phpwordpresswoocommercecartcountry

Remove a country from allowed countries when specific products are in WooCommerce cart


I want to do something simple: do not ship a particular product to Canada.

Here's the easiest way to do it in my opinion: if that particular product is present in the cart, remove Canada from checkout page.

Particular products:
1- https://constructioncovers.com/product/insulated-cement-curing-blankets/ (ID: 12616)
2- https://constructioncovers.com/product/insulated-construction-tarps/ (ID: 15631)

My research:
This article gave me a way to find products in cart and perform any action if condition is true: https://businessbloomer.com/woocommerce-easily-check-product-id-cart/ This article gave me a way to remove specific country from checkout page How to remove specific country in WooCommerce I have combined and modified the two codes to try and accomplish my task. Here's my code:

function unset_country_on_condition( $country ) {
    $product_id = 15631;
    $product_id_2 = 12616; 
    $product_cart_id = WC()->cart->generate_cart_id( $product_id );
    $product_cart_id_2 = WC()->cart->generate_cart_id( $product_id_2 );
    $in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
    $in_cart_2 = WC()->cart->find_product_in_cart( $product_cart_id_2 );
    if ( $in_cart || $in_cart_2 ) {
        unset($country["CA"]);
        return $country;
    }
}
add_filter( 'woocommerce_countries', 'unset_country_on_condition', 10, 1 );

But the above function doesn't work
. It makes the country dropdown empty resulting in a site-wide warning notice.

Can someone point out what I am doing wrong?

Screenshots: enter image description here enter image description here


Solution

  • Update 2024: (replaced initial "woocommerce_countries" hook)

    The following will remove "Canada" from allowed countries when specific products are in cart:

    add_filter( 'woocommerce_countries_allowed_countries', 'restrict_allowed_countries_based_on_products', 10, 1 );
    function restrict_allowed_countries_based_on_products( $countries ) {
        // Only on cart and checkout pages
        if( is_cart() || ( is_checkout() && !is_wc_endpoint_url() ) ) {
            $country_code  = 'CA'; // Define the targeted country code to disable
            $product_ids   = array(15631, 12616); // Define the targeted product IDs
            $product_found = false; // Initialize
    
            // Loop through cart items
            foreach( WC()->cart->get_cart() as $item ){
                // Check if one of the targeted categories is assigned
                if( in_array( $item['product_id'], $product_ids ) ){
                    $product_found = true;
                    break; // Stop the loop
                }
            }
    
            // Remove the targeted country if any targeted product is found
            if ( $product_found && isset($countries[$country_code]) ){
                unset($countries[$country_code]);
            }
        }
        return $countries;
    }
    

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


    For "Ship to", targeting shipping countries only, use additionally:

    add_filter( 'woocommerce_countries_shipping_countries', 'restrict_allowed_countries_based_on_products', 10, 1 ); 
    

    Related: Remove a country from allowed countries if specific product category is in WooCommerce cart