2
votes

In Woocommerce, I am trying to display a shipping badge which updates based on defined shipping classes.

The problem I have is when I have a variable product with the variants having different classes. I need the badge to update depending on the selection.

For example, when a variable product has a single and carton option and the single has a 10 class and the carton has a bulk1 class I need the badge to update when the carton is selected from the options.

I am not sure how to get the variant shipping class rather than the single product shipping class.

Here is how far I have got:

 function rod_shipping_banner() {

        if( $product->is_type( 'simple' ) ){
            $product = wc_get_product();

            $shipping_class = $product->get_shipping_class();

            switch ( $shipping_class ) {
                case '10':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="/wp-content/uploads/2019/03/10-shipping-small.gif" alt="$10 Flat Rate"></a></div>';
                    break;

                case 'bulk1':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="/wp-content/uploads/2019/03/Bulky1.gif"alt="Bulky class 1"></a></div>';
                    break;

                case 'bulk2':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="wp-content/uploads/2019/03/Bulky_2.gif"alt="Bulky class 2"></a></div>';
                    break;
            }
        } elseif( $product->is_type( 'variable' ) ){

            $product = wc_get_product();
            $shipping_class = $product->get_shipping_class();
            switch ( $shipping_class ) {
                case '10':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="/wp-content/uploads/2019/03/10-shipping-small.gif" alt="$10 Flat Rate"></a></div>';
                    break;

                case 'bulk1':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="/wp-content/uploads/2019/03/Bulky1.gif"alt="Bulky class 1"></a></div>';
                    break;

                case 'bulk2':
                    echo '<div class="woocommerce-info"><a href="/shipping-policy/"target="_blank"><img src="wp-content/uploads/2019/03/Bulky_2.gif"alt="Bulky class 2"></a></div>';
                    break;
            }

        }

    }
    add_action( 'woocommerce_single_product_summary_price', 
1

1 Answers

1
votes

There are some errors and mistakes in your code:

  • The hook woocommerce_single_product_summary_price doesn't exist;
  • You need to add global $product; to get the WC_Product object as wc_get_product() is null.
  • There is no difference between simple and variable products, to get the product shipping class.
  • For badges, use <span class="onsale"> … </span> instead of <div class="woocommerce-info"> … </div> that is used by Woocommerce notices…
  • You can merge your 2 function in one as they are using the same hook and priority

Also your question is not really understandable and clear.

The following revisited code, will display conditionally custom badges for specific defined shipping classes and product tag as well for simple products than variable ones:

add_action( 'woocommerce_before_single_product_summary', 'additional_single_product_badges', 10 );
function additional_single_product_badges() {
    global $product;

    ##  ----  SHIPPING CLASSES  ----  ##

    // Define the related shipping classes data in this multidimensional array
    $shipping_class_badges_data = [
        '10'    => ['2019/03/10-shipping-small.gif' => '$10 Flat Rate'],
        'bulk1' => ['2019/03/Bulky1.gif'            => 'Bulky class 1'],
        'bulk2' => ['2019/03/Bulky2.gif'            => 'Bulky class 2'],
    ];

    if( $shipping_class = $product->get_shipping_class() ) {
        foreach( $shipping_class_badges_data as $key => $badge ) {
            if ( $shipping_class == $key ) {
                foreach( $badge as $img_src => $alt_text ) {
                    $html  = '<a href="'.home_url("/shipping-policy/").'" "target="_blank">';
                    $html .= '<img src="'.home_url("/wp-content/uploads/".$img_src).'" alt="'.$alt_text.'" />';
                    $html .= '</a>';
                }
                echo ' <span class="onsale shipping-badge">'.$html.'</span>';
                break;
            }
        }
    }


    ##  ----------  TAGS  ----------  ##

    // Define the related product tags data in this multidimensional array
    $product_tags_badges_data = [
        'amarock'  => ['2019/03/Asset-4.png' => 'Tag (test)'],
    ];

    // Get the product tag(s) set in the current product
    $product_tags_slugs = wp_get_post_terms( $product->get_id(), 'product_tag', ['fields' => 'slugs'] );

    if( sizeof($product_tags_slugs) > 0 ) {
        foreach( $product_tags_badges_data as $key => $badge ) {
            if ( in_array($key, $product_tags_slugs) ) {
                foreach( $badge as $img_src => $alt_text ) {
                    $html = '<img src="'.home_url("/wp-content/uploads/".$img_src).'" alt="'.$alt_text.'" />';;
                }
                echo ' <span class="onsale tag-badge">'.$html.'</span>';
            }
        }
    }
}

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


See it in action on this variable product screenshot:

enter image description here


Related to your comments, for product variations:

To make it work for the product variations:
You can set a default shipping class in the parent variable product.

If each product variation has a different shipping class, this will not work.
It requires something different and quite complicated with javascript, as product variations are selected/changed on client side (live event), so PHP can't handle alone that.