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 custom post type - case - for which I am building an archive page. There are three custom taxonomies for this type - micro_organisms, infection_types, and antibiotic_types. These taxonomies are hierarchical, and have a variety of terms, up to three levels deep. For the given post type, I'm wanting to list terms for, say, the antibiotic_types taxonomy, that are used by any case entries.

While a term within the antibiotic_types taxonomy may be used by any of the case entries, I want to show the hierarchy leading to the selected term.

So far, I've got the following working, which results in a flat list of just the selected terms, not reflecting the hierarchy the terms are in.

// sourced from:
// http://wordpress.stackexchange.com/questions/66015/how-to-get-a-list-of-taxonomy-terms-which-are-being-used-only-within-certain-pos
function get_terms_by_post_type( $taxonomies, $post_types ) {
    global $wpdb;
    $query = $wpdb->get_results( "SELECT t.*, COUNT(*) AS count from $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id WHERE p.post_type IN('" . join( "', '", $post_types ) . "') AND tt.taxonomy IN('" . join( "', '", $taxonomies ) . "') GROUP BY t.term_id");
    return $query;
}
?>
...
<ul class="taxonomy-term-list">
<?php
$terms = get_terms_by_post_type(array($tax), array('case'));

foreach ($terms as $term):
    $termData = get_term_by('id', $term->term_id, $tax);
    $termName = $termData->name;
    $termUrl = get_term_link($termData);
?>
    <li class="taxonomy-term"><a href="<?php echo $termUrl; ?>?post_type=<?php echo $type; ?>"><?php echo $termName; ?> (<?php echo $term->count; ?>)</a></li>
<?php
endforeach;
?>
</ul>

The output resembles:

  • penicillin-g
  • ceftriaxone
  • amphotericin-b
  • 5-flucytosine

While the desired output is:

  • beta-lactams
    • cephalosporins
      • ceftriaxone
    • penicillins
      • penicillin-g
  • antifungals
    • amphotericin-b
    • 5-flucytosine

I've also tried using the following:

wp_list_categories(
    array(
        'taxonomy' => 'antibiotic_types',
        'hierarchical' => 1,
        'hide_empty' => 1,
        'title_li' => ''
    )
);

Which shows all of the terms for the given taxonomy, even those not used by any case entries.

Having browsed the function reference, it doesn't look as if there is any built-in function for doing what I want to achieve, not directly anyway. I haven't done much with taxonomy queries until now. Any suggestions?

share|improve this question
    
Have you tried using a custom walker? paulund.co.uk/display-categories-of-a-custom-post-type –  gdaniel Oct 14 '13 at 22:15
add comment

1 Answer

up vote 1 down vote accepted

If you see doc for wp_list_categories in codex, you'll se that it accepts a include param, that should contain a comma separed list of categorys ids.

So if you change your function get_terms_by_post_type creating the function get_terms_id_by_post_type to retrieve only the term ids, just like:

function get_terms_id_by_post_type( $taxonomies, $post_types ) {
    global $wpdb;
    $query = $wpdb->get_col( "SELECT t.term_id from $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id INNER JOIN $wpdb->term_relationships AS r ON r.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN $wpdb->posts AS p ON p.ID = r.object_id WHERE p.post_type IN('" . join( "', '", $post_types ) . "') AND tt.taxonomy IN('" . join( "', '", $taxonomies ) . "') GROUP BY t.term_id");
    return $query;
}

Then you can:

// retrieve the term ids used by post type
$terms = get_terms_id_by_post_type( array($tax), array('case') );

// if that terms exist implode in a commasepared string
$term_list = ! empty($terms) ? implode(',', $terms) : false;

// use wp_list_categories with include param to included only used terms
if ( $term_list ) {
  wp_list_categories(
    array(
        'taxonomy' => 'antibiotic_types',
        'hierarchical' => 1,
        'hide_empty' => 1,
        'title_li' => '',
        'include' => $term_list
    )
  );
}
share|improve this answer
    
Good tip on the include parameter. I hadn't thought of using that to limit the function results to the current terms. With some additional code I was able to assemble a function to handle the work for me. –  Grant Palin Oct 22 '13 at 7:18
    
With a minor caveat: for the hierarchical terms to appear in tree form, it is necessary to assign any ancestor terms to content along with a targeted term. Otherwise the result was a flat list. So for the penicillin-g term, I also needed to use the penicillins and beta-lactams terms. –  Grant Palin Oct 22 '13 at 7:20
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.