phpwordpresswoocommercecarttaxonomy-terms

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


[SOLVED] How would I adjust this to change country available in the Checkout page by Product Category and not specific Products?

limit shippable country by product category

I'm attempting this:

/* HIDE U.S. as a country destination if category is "Canada Only" */

add_filter( 'woocommerce_countries', 'products_disable_country', 10, 1 );
function products_disable_country( $countries ) {

    if( is_cart() || is_checkout() ) {
    
        $product_cat = array(195);
    
        foreach( WC()->cart->get_cart() as $item ){
            if( in_array( $item['product_cat'], $product_cat ) ){
                unset($countries["US"]);
                return $countries;
            }
        }
    }
    
    return $countries;

}

But no dice yet...

Used this answer code as a base:
Remove a country from allowed countries when specific products are in WooCommerce cart


Edit (Added some screenshots):

Product is Lemon Tarts, categorized as "Canada Only":.

enter image description here

Category ID for that is 195:

enter image description here

Checkout still shows US as an option in the shipping section:

enter image description here

Thanks Loic! Your final update worked perfectly, see below: enter image description here

You're a star!


Solution

  • Update (replaced initial "woocommerce_countries" hook)

    To check if a product (or an item) is assigned to a product category term, you should use has_term() conditional WordPress function like:

    add_filter( 'woocommerce_countries_allowed_countries', 'allowed_countries_for_product_category', 10, 1 );
    function allowed_countries_for_product_category( $countries ) {
        // Only on cart and checkout pages
        if( is_cart() || ( is_checkout() && !is_wc_endpoint_url() ) ) {
            $country_code   = 'US'; // Define the targeted country code to disable
            $targeted_terms = array(195); // Define your category(ies) (terms IDs, slugs or names)
            $category_found = false; // Initializing
    
            // Loop through cart items
            foreach ( WC()->cart->get_cart() as $item ) {
                // Check if one of the targeted categories is assigned
                if( has_term($targeted_terms, 'product_cat', $item['product_id']) ) {
                    $category_found = true; // Tag as found
                    break; // Stop the loop
                }
            }
    
            // Remove the targeted country if any targeted category is found
            if ( $category_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', 'allowed_countries_for_product_category', 10, 1 ); 
    

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