13

How would I get the top-level parent of a given term?

I am using wp_get_object_terms to get taxonomy terms on posts, but instead of showing all tagged terms, I only want to show tagged terms' top-level parents.

So if these are my selected terms, I only want to show Breakfast, Lunch and Dinner.

x BREAKFAST
   x Cereal
   x Eggs
  LUNCH
     Hamburger
   x Pizza
  DINNER
     Fish
        Bass
      x Salmon
        Trout
     Lasagna

How can I do this?

21

Thanks to Ivaylo for this code, which was based on Bainternet's answer.

The first function below, get_term_top_most_parent, accepts a term and taxonomy and returns the the term's top-level parent (or the term itself, if it's parentless); the second function (get_top_parents) works in the loop, and, given a taxonomy, returns an HTML list of the top-level parents of a post's terms.

// Determine the top-most parent of a term
function get_term_top_most_parent( $term, $taxonomy ) {
    // Start from the current term
    $parent  = get_term( $term, $taxonomy );
    // Climb up the hierarchy until we reach a term with parent = '0'
    while ( $parent->parent != '0' ) {
        $term_id = $parent->parent;
        $parent  = get_term( $term_id, $taxonomy);
    }
    return $parent;
}

Once you have the function above, you can loop over the results returned by wp_get_object_terms and display each term's top parent:

function get_top_parents( $taxonomy ) {
    // get terms for current post
    $terms = wp_get_object_terms( get_the_ID(), $taxonomy );
    $top_parent_terms = array();

    foreach ( $terms as $term ) {
        //get top level parent
        $top_parent = get_term_top_most_parent( $term, $taxonomy );
        //check if you have it in your array to only add it once
        if ( !in_array( $top_parent, $top_parent_terms ) ) {
            $top_parent_terms[] = $top_parent;
        }
    }

    // build output (the HTML is up to you)
    $output = '<ul>';
    foreach ( $top_parent_terms as $term ) {
          //Add every term
          $output .= '<li><a href="'. get_term_link( $term ) . '">' . $term->name . '</a></li>';
    }
    $output .= '</ul>';

    return $output;
}
  • I'd love to see a modification that wouldn't just print out the top-level terms but, rather, all terms beneath the top-most parent, hierarchically. – Robert Andrews Dec 22 '18 at 0:14
  • @RobertAndrews If you just need the children of a single term, you can use WordPress's built-in get_term_children( $term, $taxonomy ) (documentation). If you wanted to to get all children of a given term's top-level parent, you could pass the above result into it, like this: get_term_children( get_term_top_most_parent( $term, $taxonomy ), $taxonomy ). – supertrue Jan 4 at 21:12
  • What is $term in this case, ie. the object, the name of the term, the prefixed taxonomyname_number? In all cases, this method is extremely long to load. I've been waiting for the page to load for several minutes now. – Robert Andrews Jan 4 at 21:54
  • As originally written it expected an ID, but I edited the answer to allow a term ID or WP_Term object. You're not the only one reporting an issue with this code—ideally it should be rewritten to use WP's built-in get_ancestors function, which was new and not well documented when the answer was written. I will post a new answer when I've had time to test. – supertrue Jan 5 at 4:14
19

Since 3.1.0, get_ancestors() is available. It returns an array of ancestors from lowest to highest in the hierarchy.

  • 1
    This is the correct answer in my opinion. – numediaweb Jul 5 '15 at 10:14
  • 1
    This is the best answer. – Mark Jul 22 '15 at 21:28
8

Here is a simple function that will get you the top most parent term of any given term:

function get_term_top_most_parent( $term_id, $taxonomy ) {
    $parent  = get_term_by( 'id', $term_id, $taxonomy );
    while ( $parent->parent != 0 ){
        $parent  = get_term_by( 'id', $parent->parent, $taxonomy );
    }
    return $parent;
}

Once you have this function you can just loop over the results returned by wp_get_object_terms:

$terms =  wp_get_object_terms( $post->ID, 'taxonomy' );
$top_parent_terms = array();
foreach ( $terms as $term ) {

    //Get top level parent
    $top_parent = get_term_top_most_parent( $term->ID, 'taxomony' );

    //Check if you have it in your array to only add it once
    if ( !in_array( $top_parent->ID, $top_parent_terms ) ) {
        $top_parent_terms[] = $top_parent;
    }
}
  • Thanks! I'm trying this now. FYI I think you're missing a close paren in line 1 of the function. – supertrue Aug 3 '11 at 13:19
  • do I need to add $taxonomy as a second parameter in $top_parent? – supertrue Aug 3 '11 at 13:20
  • I added the $taxonomy parameter but am getting an error when I use this code, here: gist.github.com/1122631 – supertrue Aug 3 '11 at 13:33
  • yeah you do. i updated the answer. – Bainternet Aug 3 '11 at 13:33
  • 1
    your function seems broken your foreach loops are overlapping try this: pastebin.com/u48dxzap and if you still get an error paste all of you code and i'll check – Bainternet Aug 3 '11 at 17:36
5
/**
 * Get top level term
 */
function get_top_level_term($term,$taxonomy){
    if($term->parent==0) return $term;
    $parent = get_term( $term->parent,$taxonomy);
    return get_top_level_term( $parent , $taxonomy );
}
  • 1
    Please add an explanation along with your code. – s_ha_dum Oct 18 '13 at 4:43
4

I had the same problem and I solved easily. Check this out:

Define $taxonomy. It can be the slug of the taxonomy you want to get the data. After doing this, you can simply do this:

<?php
    $postterms = wp_get_post_terms($post->ID, $taxonomy);   // get post terms
    $parentId = $postterms[0]->parent;                      // get parent term ID
    $parentObj = get_term_by('id', $parentId, $taxonomy);   // get parent object 
?>

Now you got something like this:

object(stdClass)#98 (11) {
  ["term_id"]=>
  int(3)
  ["name"]=>
  string(8) "Esportes"
  ["slug"]=>
  string(8) "esportes"
  ["term_group"]=>
  int(0)
  ["term_taxonomy_id"]=>
  int(3)
  ["taxonomy"]=>
  string(17) "noticiaseditorias"
  ["description"]=>
  string(0) ""
  ["parent"]=>
  int(0)
  ["count"]=>
  int(4)
  ["object_id"]=>
  int(123)
  ["filter"]=>
  string(3) "raw"
}

And you can use $parentObj to get slug, name, id, whatever. Just by using $parentObj->slug or $parentObj->name as exemple.

2

Easiest way:

$rootId = end( get_ancestors( $term_id, 'my_taxonomy' ) );
$root = get_term( $rootId, 'my_taxonomy' );
echo $root->name;
0

Maybe this helps: get_ancestors( $object_id, $object_type );

codex.wordpress.org

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.