0

Our WooCommerce products have two custom taxonomies: sizes and colors.

I'm trying to display the custom toxonomy terms for a product on its single product page. I'm using the woocommerce_single_product_summary action hook. I can't get both taxonomies to display at the same time.

Here's my code so far:

<?php
/**
 * display a woocommerce product's custom taxonomy terms on single product pages
 */

function display_single_product_sizes_after_summary() { 
    global $post;
    
    $size_terms = get_the_terms( $post->ID , array( 'sizes') );
    // begin creating html markup
    $size_markup = '';
    if(!empty($size_terms)) {
        $size_markup .= "<p>Similar size shades: ";
    }
    // init counter
    $is = 1;
    foreach ( $size_terms as $size_term ) {
        $size_markup .= '<a href="/shades/size/' . $size_term->slug . '">' . $size_term->name . '</a>';
        //  Add comma (except after the last item)
        $size_markup .= ($is < count($size_terms))? ", " : "";
        // Increment counter
        $is++;
        //finish the markup
        if(!empty($size_terms)) {
            $size_markup .= "</p>";
        }
    }
    echo $size_markup;
};

function display_single_product_colors_after_summary() { 
    global $post;
    
    $color_terms = get_the_terms( $post->ID , array( 'colors') );
    // begin creating html markup
    $color_markup = '';
    if(!empty($color_terms)) {
        $color_markup .= "<p>Similar color shades: ";
    }
    // init counter
    $ic = 1;
    foreach ( $color_terms as $color_term ) {
        $color_markup .= '<a href="/shades/color/' . $color_term->slug . '">' . $color_term->name . '</a>';
        //  Add comma (except after the last item)
        $color_markup .= ($ic < count($color_terms))? ", " : "";
        // Increment counter
        $ic++;
        //finish the markup
        if(!empty($color_terms)) {
            $color_markup .= "</p>";
        }
    }
    echo $color_markup;
};

function display_single_product_terms_after_summary() {
    display_single_product_sizes_after_summary();
    display_single_product_colors_after_summary();
};
add_action( 'woocommerce_single_product_summary', 'display_single_product_terms_after_summary', 101, 0 );
?>

This outputs the following:

Similar size shades: Small

Similar color shades:

If I reverse the order of the two sub-functions in display_single_product_traits_after_summary the output changes to:

Similar color shades: Blue

Similar size shades:

I've tried to use a reset at the end of each subfunction. I've tried:

    echo $size_markup;
    wp_reset_postdata();

and:

    echo $color_markup;
    wp_reset_postdata();

This makes no difference.

I've also tried:

    echo $size_markup;
    rewind_posts();

and:

    echo $color_markup;
    rewind_posts();

This breaks the page altogether.

What is my mistake here, and how can I get the terms from both taxonomies to display?

0

The WordPress documentation shows that an array is an acceptable argument for the taxonomy in get_the_terms (https://developer.wordpress.org/reference/functions/get_the_terms/). An array works if you are trying to get multiple taxonomies. It even works if you are trying to get just one taxonomy. But getting two single taxonomy arrays sequentially is what breaks this code.

In the originally posted code, replacing this:

$size_terms = get_the_terms( $post->ID , array( 'sizes') );

with this instead:

$size_terms = get_the_terms( $post->ID , 'sizes' );

And also replacing this:

$color_terms = get_the_terms( $post->id , array( 'colors') );

with this instead:

$color_terms = get_the_terms( $post->id , 'colors' );

solves the problem.

Another alternative that works is to retrieve both sets of taxonomy terms at once, and then tease apart the WP_Term Object to find exactly what you want. This is probably the better solution in most cases.

function display_single_product_taxonomy_terms() {
    global $post;
    
    $tax_terms = get_the_terms( $post->ID , array( 'sizes','colors') );
    // create the markup variables
    $color_markup = '';
    $size_markup = '';
    // init counters
    $color_counter = 0;
    $size_counter = 0;
    
    foreach ( $tax_terms as $tax_term ) {
        if( $tax_term->taxonomy == 'colors' ) {
            // this is a colors term; increment color counter
            $color_counter++;
            // add to color markup
            $color_markup .= ($color_counter > 1)? "; " : "";
            $color_markup .= '<a href="/shades/color/' . $tax_term->slug . '">' . str_replace(", and,"," and",str_replace("-", ", ", $tax_term->slug)) . '</a>';
        } else {
            // this is a sizes term; increment size counter
            $size_counter++;
            // add to size markup
            $size_markup .= ($size_counter > 1)? "; " : "";
            $size_markup .= '<a href="/shades/size/' . $tax_term->slug . '">' . str_replace("-", " ", $tax_term->slug) . '</a>';
        }
    };
    
    echo '<div class="single-product-taxonomy-terms">' . PHP_EOL;
    if ( $size_counter > 0 ) {
        echo '<p>'. __("Similar size shades: ","bright-side") . $size_markup . '</p>' . PHP_EOL;
    };
    if ( $color_counter > 0 ) {
        echo '<p>' . __("Similar color shades: ","bright-side") . $color_markup . '</p>' . PHP_EOL;
    };
    echo '</div>' . PHP_EOL;
};
add_action( 'woocommerce_single_product_summary', 'display_single_product_taxonomy_terms', 101, 0 );
  • If anyone knows why two sequential get_the_terms - each with single-taxonomy arrays - does not work, I'd like to understand that. – hommealone Jul 6 '20 at 16:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.