How to get a list of taxonomy terms which are being used only within certain post types?

I have a custom taxonomy called ‘locations’ which is being shared across a bunch of post types. I want to make a select field dropdown list of my locations (terms) to let users go to the taxonomy term page for each specific location; however I want to exclude some terms which are used in one post type and perhaps not in the others.

Is there a way to accomplish this?

Related posts

Leave a Reply

1 comment

  1. I’m not a programmer so there’s probably a far more efficient/correct way of doing this.

    Put this in functions.php or a custom plugin:

    function get_terms_by_post_type( $taxonomies, $post_types ) {
        global $wpdb;
        $query = $wpdb->get_results( "SELECT t.*, 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;
    }
    
    function show_post_type_terms($taxonomy, $posttype = null ) {
       global $post;
       if(!isset($posttype)) $posttype = get_post_type( $post->ID );
       $terms = get_terms_by_post_type( array($taxonomy), array($posttype) );
       echo '<ul>';
       foreach($terms as $term) {
          $output = '<li><a href="'.get_bloginfo('url').'/'.$taxonomy.'/'.$term->slug.'/?post_type='.$posttype.'">'.$term->name.'</a></li>';
          echo $output;
       }
       echo '</ul>';
    }
    

    Usage examples:

    1. Put <?php show_post_type_terms('taxonomy_name'); ?> into custom post type archive template file to show a list of terms of taxonomy_name, excluding all terms that are not used by post of the current custom post type, and linking to a term archive which shows only post of that specific post type.
    2. Put <?php show_post_type_terms('taxonomy_name', 'custom_post_type_name'); ?> in any other template file to do the same for a specific custom post type.
    3. You could also adapt it to act as a shortcode that you can place directly into a post or page, with something like [show_post_type_terms taxonomy="taxonomy_name" posttype="post_type_name"]. Let me know if you’re looking for the code for this.

    Adapted from this. ($wpdb->prepare was changed to $wpdb->get_results because of this)