Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

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;
}
share|improve this question
add comment

3 Answers

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;
  }

?>
share|improve this answer
    
How would you handle more than two levels of categories? –  Anriëtte Myburgh Jun 28 '12 at 9:38
add comment
up vote 0 down vote accepted

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;
}
share|improve this answer
add comment

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;
share|improve this answer
add comment

protected by Community Apr 5 at 1:37

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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