Get main parent categories for a product

Can someone please help me, I’m looking for a way to find the main parent product category of a WooCommerce product? Say, the product is marked under Gadgets, but the main parent of them all is Electronics.

I want this per post, as I want to add a class to each post signifying its main parent product_cat.

Read More

Please remember, product categories are custom taxonomy, and cannot be retrieved using get_category_parents(). They are listed as terms.

Thanks in advance.

// edit:

This is the code I have already, I’m calling this on each post and my posts are rendered similar to an archive page.

function all_cat_classes($post) {
    $cats = "";

    $terms = get_the_terms($post->ID, "product_cat");

    $count = 0;
    $count = count($terms);
    $key = 0;
    foreach ($terms as $cat) {

        $key++;
    }

    return $cats;
}

Related posts

Leave a Reply

3 comments

  1. just to offer a alternative solution that might help somebody:

    code

    function wc_origin_trail_ancestor( $link = false, $trail = false ) {
    
        if (is_product_category()) {
            global $wp_query;
            $q_obj = $wp_query->get_queried_object();
            $cat_id = $q_obj->term_id;
    
            $descendant = get_term_by("id", $cat_id, "product_cat");
            $descendant_id = $descendant->term_id;
    
            $ancestors = get_ancestors($cat_id, 'product_cat');
            $ancestors = array_reverse($ancestors);
    
            $origin_ancestor = get_term_by("id", $ancestors[0], "product_cat");
            $origin_ancestor_id = $origin_ancestor->term_id;
    
            $ac = count($ancestors);
    
        } else if ( is_product() ) {
    
            $descendant = get_the_terms( $post->ID, 'product_cat' );
            $descendant = array_reverse($descendant);
            $descendant = $descendant[0];
            $descendant_id = $descendant->term_id;
    
            $ancestors = array_reverse(get_ancestors($descendant_id, 'product_cat'));
            $ac = count($ancestors);
    
        }
    
    
        $c = 1;
        if( $trail == false ){
    
            $origin_ancestor_term = get_term_by("id", $ancestors[0], "product_cat");
            $origin_ancestor_link = get_term_link( $origin_ancestor_term->slug, $origin_ancestor_term->taxonomy );
    
            if($link == true) 
                echo '<a href="'. $origin_ancestor_link .'">';
            echo $origin_ancestor_term->name;
            if($link == true) 
                echo '</a>';
    
        }else{
    
            foreach ($ancestors as $ancestor) {
                $ancestor_term = get_term_by("id", $ancestor, "product_cat");
                $ancestor_link = get_term_link( $ancestor_term->slug, $ancestor_term->taxonomy );
    
                if($c++ == 1) 
                    echo '» '; 
                else if($c++ != 1 || $c++ != $ac) 
                    echo ' » ';
    
                if($link == true) 
                    echo '<a href="'. $ancestor_link .'">';
                echo  $ancestor_term->name;
                if($link == true) 
                    echo '</a>';
    
            }
    
            $descendant_term = get_term_by("id", $descendant_id, "product_cat");
            $descendant_link = get_term_link( $descendant_term->slug, $descendant_term->taxonomy );
    
            echo ' » ';
            if($link == true) 
                echo '<a href="'. $descendant_link .'">';
            echo $descendant->name;
            if($link == true) 
                echo '</a>';
    
        }
    
    }
    

    how to use

    • just toplevel, origin ancestor; without link
      wc_origin_trail_ancestor();
    • just toplevel, origin ancestor; with link
      wc_origin_trail_ancestor(true);
    • ancestor trail; without link
      wc_origin_trail_ancestor(false,true);
    • ancestor trail; with link
      wc_origin_trail_ancestor(true,true);

    notes

    • won’t work if a product has multiple main-/toplevel-categories, or at least won’t show them all;
    • same should be the case for multiple subcategories on the same level;
    • I did no further tests concerning above points, because the function does all I wanted for that project;
  2. I wrote my own function to go all the way up the “chain”. My recursive might not be the best implementation you’ve seen, but it works.

    function get_parent_terms($term) {
        if ($term->parent > 0) {
            $term = get_term_by("id", $term->parent, "product_cat");
            if ($term->parent > 0) {
                get_parent_terms($term);
            } else return $term;
        }
        else return $term;
    }
    
    # Will return all categories of a product, including parent categories
    function all_cat_classes($post) {
        $cats = ""; 
        $terms = get_the_terms($post->ID, "product_cat");
        $key = 0;
    
        // foreach product_cat get main top product_cat
        foreach ($terms as $cat) {
            $cat = get_parent_terms($cat);
            $cats .= (strpos($cats, $cat->slug) === false ? $cat->slug." " : "");
            $key++;
        }
    
        return $cats;
    }
    
  3. You can try this:

    <?php
      $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
      $parents = get_the_terms($term->parent, get_query_var('taxonomy') );
    
      foreach( $parents as $parent ) {
        echo $parent->name;
      }
    
    ?>