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.

I have a hierarchical custom taxonomy which I can display using print_r(get_the_terms( $post->ID, 'taxonomic_rank' ));:

Array
(
    [46] => stdClass Object
        (
            [term_id] => 46
            [name] => Aplocheilidae
            [slug] => aplocheilidae
            [term_group] => 0
            [term_taxonomy_id] => 53
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 39
            [count] => 1
            [object_id] => 443
        )

    [47] => stdClass Object
        (
            [term_id] => 47
            [name] => Aplocheilus
            [slug] => aplocheilus
            [term_group] => 0
            [term_taxonomy_id] => 54
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 46
            [count] => 1
            [object_id] => 443
        )

    [39] => stdClass Object
        (
            [term_id] => 39
            [name] => Cyprinodontiformes
            [slug] => cyprinodontiformes
            [term_group] => 0
            [term_taxonomy_id] => 52
            [taxonomy] => taxonomic_ranks
            [description] => 
            [parent] => 0
            [count] => 1
            [object_id] => 443
        )

)

This taxonomy will always take the following form: Order (parent) > Family (child of Order) > Sub-family (child of Family)

Is there a quick and easy way of displaying these taxonomies in the correct order, so that I could print out the following line? Order: <order>, Family: <family>, Sub-family: <sub-family>

Thanks in advance

share|improve this question
3  
Whoever down-marked me, would you please explain why? –  dunc Dec 26 '11 at 13:09
add comment

5 Answers 5

up vote 4 down vote accepted

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.

share|improve this answer
    
I couldn't be further in your debt. That is a perfect answer, and I wish I could give you more reputation!! If anyone passes this post, please +1 it so that Maugly can be rewarded as much as I'd like :) –  dunc Dec 27 '11 at 14:23
1  
No worries. I'm glad I could help :) I've also updated the code in my answer and added a simple input check... –  Michal Mau Dec 27 '11 at 15:10
    
Thanks again! :) –  dunc Dec 27 '11 at 15:13
    
Maugly, thanks for your answer, it's almost exactly what I needed- do you have any thoughts on how to use it with the archive links still attached to the terms? Thanks again –  user12391 Jan 24 '12 at 3:55
    
@Adam Take a look on get_term_link() –  Michal Mau Jan 24 '12 at 10:36
add comment

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}";
}
share|improve this answer
    
Nice work! I knew that it is possible, I just couldn't wrap my head around it back then :) I like your solution! –  Michal Mau Jan 24 '12 at 12:34
add comment

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"!

share|improve this answer
add comment

Thanks Maugly,

Here's my modified version of your code that includes the term permalinks if anyone needs it

function print_show_location( $terms = '' ){

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

// set id variables to 0 for easy check 
$country_id = $state_id = $city_id = 0;

// get country
foreach ( $terms as $term ) {
    if ( $country_id || $term->parent )
        continue;
    $country_id  = $term->term_id;
    $country_slug = $term->slug;
    $country = '<a href="'.get_term_link($country_slug, 'location').'">'.$term->name.'</a>';
}

// get state
foreach ( $terms as $term ) { 
    if ( $state_id || $country_id != $term->parent )
        continue;
    $state_id = $term->term_id;
    $state_slug = $term->slug;
    $state = '<a href="'.get_term_link($state_slug, 'location').'">'.$term->name.'</a>';
}

// get city
foreach ( $terms as $term ) { 
    if ( $city_id || $state_id != $term->parent ) 
        continue;
    $city_id = $term->term_id;
    $city_slug = $term->slug;
    $city = '<a href="'.get_term_link($city_slug, 'location').'">'.$term->name.'</a>';
}

// output
echo "$city, $state - $country";

}
share|improve this answer
add comment

Here is more universal solution of the task:

     <?php

            /**
             * Retrieve a post's terms as a list ordered by hierarchy.
             *
             * @param int $post_id Post ID.
             * @param string $taxonomy Taxonomy name.
             * @param string $term_divider Optional. Separate items using this.
             * @param string $reverse Optional. Reverse order of links in string.
             * @return string
             */
            class GetTheTermList {

                public function get_the_term_list($post_id, $taxonomy, $term_divider = '/', $reverse = false) {
                    $object_terms = wp_get_object_terms($post_id, $taxonomy);
                    $parents_assembled_array = array();
                    //***
                    if (!empty($object_terms)) {
                        foreach ($object_terms as $term) {
                            $parents_assembled_array[$term->parent][] = $term;
                        }
                    }
                    //***
                    $sorting_array = $this->sort_taxonomies_by_parents($parents_assembled_array);
                    $term_list = $this->get_the_term_list_links($taxonomy, $sorting_array);
                    if ($reverse) {
                        $term_list = array_reverse($term_list);
                    }
                    $result = implode($term_divider, $term_list);

                    return $result;
                }

                private function sort_taxonomies_by_parents($data, $parent_id = 0) {
                    if (isset($data[$parent_id])) {
                        if (!empty($data[$parent_id])) {
                            foreach ($data[$parent_id] as $key => $taxonomy_object) {
                                if (isset($data[$taxonomy_object->term_id])) {
                                    $data[$parent_id][$key]->childs = $this->sort_taxonomies_by_parents($data, $taxonomy_object->term_id);
                                }
                            }

                            return $data[$parent_id];
                        }
                    }

                    return array();
                }

                //only for taxonomies. returns array of term links
                private function get_the_term_list_links($taxonomy, $data, $result = array()) {
                    if (!empty($data)) {
                        foreach ($data as $term) {
                            $result[] = '<a rel="tag" href="' . get_term_link($term->slug, $taxonomy) . '">' . $term->name . '</a>';
                            if (!empty($term->childs)) {
                                //***
                                $res = $this->get_the_term_list_links($taxonomy, $term->childs, array());
                                if (!empty($res)) {
                                    //***
                                    foreach ($res as $val) {
                                        if (!is_array($val)) {
                                            $result[] = $val;
                                        }
                                    }
                                    //***
                                }
                                //***
                            }
                        }
                    }

                    return $result;
                }

            }
            ?>

    <?php
    //EXAMPLE OF USING

        $term_list_object = new GetTheTermList();
        $car_location = $term_list_object->get_the_term_list($post_id, 'carlocation', ', ',FALSE);

        ?>

Read about it here: http://pluginus.net/get-the-term-list-ordered-by-hierarchy/

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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