I have 5 different custom post types and one custom taxonomy. I've been able to get a taxonomy dropdown using <?php wp_dropdown_categories( $args ); ?> but I noticed that I was not able to restrict the taxonomy dropdown to show the terms which have posts from a particular post type.

Some of the comments that I got asked me to create a different taxonomy for each post type but that is not possible in my case since my custom taxonomy is for defining a location and I'd like all the 5 custom post types to use this one taxonomy.

I know that I can load the posts from a post type and get the terms from those posts and use a foreach loop to loop through these and output them as options in a select field but I don't want to use this since I would lose the hierarchy that I had set up for the taxonomy. If I can get the hierarchy using this method then I'm open to that too.

Is this possible or do I have to create separate taxonomies for each post type?

UPDATE I wanted to be able to add a custom field value also as a parameter. TheDeadMedic's answer does that.

1 Answer 1


You can use a snippet I found for querying terms that are attached to a particular post type:

function wpse_207655_terms_by_post_type_or_meta( $clauses, $taxonomy, $args ) {
    $meta_query = new WP_Meta_Query;
    $meta_query->parse_query_vars( $args );
    $post_types = '';

    if ( ! empty( $args['post_type'] ) ) {
        if ( $_post_types = array_intersect( ( array ) $args['post_type'], get_post_types() ) )
            $post_types = implode( "','", $_post_types );

    if ( $post_types || $meta_query->queries ) {
        global $wpdb;

        $clauses['join']   .= " 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";
        $clauses['orderby'] = "GROUP BY t.term_id {$clauses['orderby']}";

        if ( $post_types )
            $clauses['where'] .= " AND p.post_type IN ('$post_types')";

        if ( $meta_query->queries ) {
            $sql = $meta_query->get_sql( 'post', 'p', 'ID' );

            $clauses['join']  .= $sql['join'];
            $clauses['where'] .= $sql['where'];

    return $clauses;

add_filter( 'terms_clauses', 'wpse_207655_terms_by_post_type_or_meta', 10, 3 );

Now you can use a post_type argument in wp_dropdown_categories (that actually just gets passed onto get_terms, which is where our filter comes into play):

wp_dropdown_categories( 'taxonomy=location&post_type=X' ); 

Update: Now you can also use WP_Query meta arguments:

wp_dropdown_categories( 'meta_key=foobar' );

...or a full blown meta query:

wp_dropdown_categories( array(
    'post_type'  => 'foobar',
    'meta_query' => array(
            'key'   => 'this',
            'value' => 'that',
            'key' => 'foobar',
  • Thank you so much, TheDeadMedic! This seems to be working the way I want. Now the icing on the cake would be if it is possible to add a custom field value also as a parameter. :)
    – NJT
    Commented Nov 6, 2015 at 5:16
  • Hi TheDeadMedic, is there a way to add the custom field parameter the same way?
    – NJT
    Commented Nov 23, 2015 at 6:07
  • See revised answer. Commented Nov 23, 2015 at 10:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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