phpwoocommercecartcheckoutcountries

Display a custom message based on shipping zone and product categories in Woocommerce


I've been using Woocommerce to try to write a PHP function (as a novice hack stuff together from other posts here and elsewhere)...

:) I seem to have managed this finally (before anyone even responded to my post!), so here it is in case it proves useful to anyone - feel free to let me know of any improvements, I'm really not a PHP-person!

The function below will display a notice at the top of the cart/checkout only when products of Category 'A' are in the order and the customer is not in the UK or EU.

add_action( 'woocommerce_before_checkout_form' , 'shipping_zone_targeted_postcodes_custom_notice' );
add_action( 'woocommerce_before_cart_table', 'shipping_zone_targeted_postcodes_custom_notice' );
function shipping_zone_targeted_postcodes_custom_notice() {
  // HERE DEFINE YOUR SHIPPING ZONE NAME(S)
  $targeted_zones_names = array('UK', 'EU'); // <======  <======  <======  <======  <======  

  // Get the customer shipping zone name
  $chosen_methods    = WC()->session->get( 'chosen_shipping_methods' ); // The chosen shipping mehod
  $chosen_method     = explode(':', reset($chosen_methods) );
  $shipping_zone     = WC_Shipping_Zones::get_zone_by( 'instance_id', $chosen_method[1] );
  $current_zone_name = $shipping_zone->get_zone_name();

  // set your special category name, slug or ID here:
  $special_cat = '(CATEGORY 'A')';
  $bool = false;
  foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    $item = $cart_item['data'];
    if ( has_term( $special_cat, '(CATEGORY 'A')', $item->id ) )
      $bool = true;
  }

  if( !in_array( $current_zone_name, $targeted_zones_names ) && $bool ){
    echo '<p class="message-text">(CUSTOM TEXT)</p>';    
  }
}

My code is mostly made from this answer thread:
Display a custom message based on customer shipping zone in Woocommerce


Solution

  • There are some errors and mistakes in your code like:

    • This $special_cat = '(CATEGORY 'A')'; make an error and should need to be instead:

      $special_cat = "(CATEGORY 'A')";
      
    • In if ( has_term( $special_cat, '(CATEGORY 'A')', $item->id ) ) $item->id need to be instead $item->get_id()
      and '(CATEGORY 'A')' need to be replaced with the correct product category taxonomy which is 'product_cat', so:

      if ( has_term( $special_cat, 'product_cat', $item->get_id() ) )
      

    But for product categories you will use instead (to handle product variations too):

    if ( has_term( $special_cat, 'product_cat', $cart_item['product_id'] ) )
    

    So the functional complete code should be:

    add_action( 'woocommerce_before_checkout_form', 'shipping_zone_targeted_postcodes_custom_notice' );
    add_action( 'woocommerce_before_cart_table', 'shipping_zone_targeted_postcodes_custom_notice' );
    function shipping_zone_targeted_postcodes_custom_notice() {
    
        // HERE DEFINE YOUR SHIPPING ZONE NAME(S)
        $targeted_zones_names = array('UK', 'EU'); // <======  <======  <======  <====== 
    
        // Get the customer shipping zone name
        $chosen_methods    = WC()->session->get( 'chosen_shipping_methods' ); // The chosen shipping mehod
        $chosen_method     = explode(':', reset($chosen_methods) );
        $shipping_zone     = WC_Shipping_Zones::get_zone_by( 'instance_id', $chosen_method[1] );
        $current_zone_name = $shipping_zone->get_zone_name();
    
        // Set your special category name, slug or ID here:
        $special_cat = "(CATEGORY 'A')";
        $bool = false;
    
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            if ( has_term( $special_cat, 'product_cat', $cart_item['product_id'] ) )
                $bool = true;
        }
    
        if( ! in_array( $current_zone_name, $targeted_zones_names ) && $bool ){
            echo '<p class="message-text">(CUSTOM TEXT)</p>';    
        }
    }
    

    Code goes in function.php file of your active child theme (or active theme). Tested and works.

    Related: Display a custom message based on customer shipping zone in Woocommerce