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.

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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 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 .'" rel="nofollow noreferrer noopener">';
        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 .'" rel="nofollow noreferrer noopener">';
            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 .'" rel="nofollow noreferrer noopener">';
        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;

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

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

?>


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x