Joshua David Nelson

Bullshit Free WordPress Development

  • Services
  • Code
  • About
  • Contact

Category (Taxonomy) Dropdown Filtered By Post Type

February 19, 2016 by Joshua Nelson

Screen Shot 2016-02-19 at 9.20.28 PMWhile working on a large custom content management solution for a client I was building templates for multiple post types all sharing a common taxonomy. Most of these templates needed a dropdown to filter the results by the common taxonomy, in this case a taxonomy named “department.”

Should be fairly straight-forward, right? WordPress does offer a great function for creating taxonomy dropdowns called wp_dropdown_categories, which works with custom taxonomies as well as categories.

However, it will return all taxonomies with any posts. If you have multiple post types, you could very easily get a list of taxonomies with posts, but not the post type you want for the template – as was my issue.

Luckily, we can filter the SQL query used in the get_terms function, which is called by wp_dropdown_cateogies.

<?php
/**
* Filter the term clauses using the arguments, specifically for the wp_dropdown_categories.
*
* @see http://wordpress.stackexchange.com/questions/207655/restrict-taxonomy-dropdown-to-post-type
* @see https://www.dfactory.eu/get_terms-post-type/
*
* @param array $clauses
* @param string $taxonomy
* @param array $args
*
* @return array
*/
add_filter( 'terms_clauses', 'jdn_post_type_terms_clauses', 10, 3 );
function jdn_post_type_terms_clauses( $clauses, $taxonomy, $args ) {
// Make sure we have a post_type argument to run with.
if( !isset( $args['post_type'] ) || empty( $args['post_type'] ) )
return $clauses;
global $wpdb;
// Setup the post types in an array
$post_types = array();
// If the argument is an array, check each one and cycle through the post types
if( is_array( $args['post_type'] ) ) {
// All possible, public post types
$possible_post_types = get_post_types( array( 'public' => true ) );
// Cycle through the post types, add them to our array if they are public
foreach( $args['post_type'] as $post_type ) {
if( in_array( $post_type, $possible_post_types ) )
$post_types[] = "'" . esc_attr( $post_type ) . "\'";
}
// If the post type argument is a string, not an array
} elseif( is_string( $args['post_type'] ) ) {
$post_types[] = "'" . esc_attr( $args['post_type'] ) . "'";
}
// If we have valid post types, build the new sql
if( !empty( $post_types ) ) {
$post_types_string = implode( ',', $post_types );
$fields = str_replace( 'tt.*', 'tt.term_taxonomy_id, tt.term_id, tt.taxonomy, tt.description, tt.parent', $clauses['fields'] );
$clauses['fields'] = 'DISTINCT ' . esc_sql( $fields ) . ', COUNT(t.term_id) AS count';
$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['where'] .= ' AND p.post_type IN (' . $post_types_string . ')';
$clauses['orderby'] = 'GROUP BY t.term_id ' . $clauses['orderby'];
}
return $clauses;
}
view raw filter-term-clauses.php hosted with ❤ by GitHub

The above utilizes the term_clauses filter, and hunts for the post_type argument. The beauty of this is that we’re extending the functionality of the get_terms function directly.

This means we can use wp_dropdown_categories and simply pass our new post_type argument. Furthermore, the fallback here is the built-in function, which is a double bonus. I love the extend-ability of WordPress!

Here’s the basic usage, now that we have the filter above:

<?php
/**
* Using wp_dropdown_categories with the post type filter applied.
*
* @link https://joshuadnelson.com/category-taxonomy-dropdown-filtered-by-post-type/
*/
// Taxonomy dropdown arguments
$args = array(
'taxonomy' => 'department',
'post_type' => 'project', // filter by the post type 'project'
'echo' => true,
);
wp_dropdown_categories( $args );
view raw basic-dropdown-usage.php hosted with ❤ by GitHub

That said, I built a custom function to wrap the wp_dropdown_categories, so I could grab the current query var and add a wrapper element.

Here are some useful resources if you’re going down this rabbit hole:

  • get_terms
  • wp_dropdown_categories
  • Understanding MySQL in WordPress
  • Stack Exchange: Restrict taxonomy dropdown to post type

Filed Under: Beginner, WordPress, WordPress Tutorials Tagged With: custom post type, taxonomy

Discussion

  1. Patrick says

    March 10, 2016 at 16:06

    Ah very cool. I was wondering how to do something like this. Yet another thing to add to my list to try out. Thanks very much.

  • Twitter
  • RSS Feed URL

About Me

I'm a WordPress Engineer. I build sleek, custom websites with WordPress and Genesis.

See my services and my recent work.

Contact me to get your project started.

Gravity Forms Plugin for WordPress Fastest WordPress Hosting

Recent Posts

  • Using Font Awesome Icons for WooCommerce Grid / List Toggle
  • Disable Blog: WordPress Gone Blog-less
  • Category (Taxonomy) Dropdown Filtered By Post Type
  • Weather in WordPress with Dark Sky
  • Fixing Your Deprecated Widget Constructors in WordPress 4.3

Like This Site? Buy the WordPress theme and others by StudioPress.

StudioPress Premium WordPress Themes

Recent Posts

  • Using Font Awesome Icons for WooCommerce Grid / List Toggle
  • Disable Blog: WordPress Gone Blog-less
  • Category (Taxonomy) Dropdown Filtered By Post Type
  • Twitter
  • RSS Feed URL
  • Code Snippets
  • My Plugins
  • Make a Payment
  • Donate

© Joshua David Nelson | Hand-Forged | WordPress + Genesis | Terms of Service | Legal | Contact