Wordpress - Custom taxonomy, get_the_terms, listing in order of parent > child

There are probably some better ways to do this but you can always do a three simple foreach loops.

I wrote an example function that does the job well and should serve you as a good starting point:

function print_taxonomic_ranks( $terms = '' ){

    // check input
    if ( empty( $terms ) || is_wp_error( $terms ) || ! is_array( $terms ) )
        return;

    // set id variables to 0 for easy check 
    $order_id = $family_id = $subfamily_id = 0;

    // get order
    foreach ( $terms as $term ) {
        if ( $order_id || $term->parent )
            continue;
        $order_id  = $term->term_id;
        $order     = $term->name;
    }

    // get family
    foreach ( $terms as $term ) { 
        if ( $family_id || $order_id != $term->parent )
            continue;
        $family_id = $term->term_id;
        $family    = $term->name;
    }

    // get subfamily
    foreach ( $terms as $term ) { 
        if ( $subfamily_id || $family_id != $term->parent ) 
            continue;
        $subfamily_id = $term->term_id;
        $subfamily    = $term->name;
    }

    // output
    echo "Order: $order, Family: $family, Sub-family: $subfamily";

}

Let it live in your functions.php file and use it in your templates like this:

print_taxonomy_ranks( get_the_terms( $post->ID, 'taxonomic_rank' ) );

NOTE: Looping the same array three times around sounds a bit stupid but on the other hand it's a quick and easy solution which is easy to read, extend and maintain.


Though Maugly's approach seem a bit more readable but running a loop 3 times over the array doesn't seem right to me. So here is just another approach which might be less readable for some but works without running loop 3 times.

function print_taxonomy_ranks( $terms ) {
    // if terms is not array or its empty don't proceed
    if ( ! is_array( $terms ) || empty( $terms ) ) {
        return false;
    }

    foreach ( $terms as $term ) {
        // if the term have a parent, set the child term as attribute in parent term
        if ( $term->parent != 0 )  {
            $terms[$term->parent]->child = $term;   
        } else {
            // record the parent term
            $parent = $term;
        }
    }

    echo "Order: $parent->name, Family: {$parent->child->name}, Sub-Family: {$parent->child->child->name}";
}

I had a situation where a post could be tagged with multiple category groups, and multiple children within parent categories, so I wanted my hierarchy to reflect that. I also just wanted a few lines of code:

$terms = get_the_terms($id, 'department_categories');
foreach($terms as $key => $term){
    if($term->parent != 0){
        $terms[$term->parent]->children[] = $term;
        unset($terms[$key]);
    }
}

Basically after it finds a category's parent, it moves it to the parent's obj as a child, and then removes it from it's original position in the array. I've tested this using multiple siblings, children, and different levels of categories.

Hope someone else finds this useful in case they're just looking for some logic guidance rather than a "plugin"!