Filter wp_dropdown_categories by post type.
<?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 ); |
<?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; | |
} |
<?php | |
/** | |
* A wrapper function for the custom dropdown, sets the current value by a url query var, | |
* adds a custom label, and a wrapper element. | |
* | |
* @author Joshua David Nelson, josh@joshuadnelson.com | |
* | |
* @link https://joshuadnelson.com/category-taxonomy-dropdown-filtered-by-post-type/ | |
* | |
* @see https://codex.wordpress.org/Function_Reference/wp_dropdown_categories | |
* | |
* @param array $args | |
* | |
* @return string $output | |
*/ | |
function jdn_get_custom_taxonomy_dropdown( $args ) { | |
// Taxonomy dropdown arguments | |
$defaults = array( | |
'taxonomy' => false, // required, the default here is a failsafe | |
'post_type' => false, // pass a value if you want to | |
'echo' => false, // true to echo, false for return | |
'label' => false, // false or pass a string for the label | |
'query_var' => false, // pass the query variable for the selected dropdown value | |
'id' => '', // set this and the default category 'name' argument | |
'wrap' => 'div', // the wrapper element. set to false to skip it. | |
'wrap_class' => 'select-wrap', // The custom wrapper class, set to false to skip it | |
); | |
$args = wp_parse_args( $args, $defaults ); | |
// Be sure we're good to go. | |
if( ! $args['taxonomy'] ) | |
return false; | |
// Current value of query variable, if there is one | |
if( $args['query_var'] ) { | |
$query_tax = get_query_var( esc_attr( $args['query_var'] ), false ); | |
$current = $query_tax ? sanitize_text_field( $query_tax ) : ''; | |
$args['selected'] = $current; | |
} | |
// We're returning the output of wp_dropdown_cateogies, but we need to know how the end user wants it back in this function, | |
// so we'll store that value as a variable and reset the echo argument for the wp_dropdown_categories. | |
$echo = esc_attr( $args['echo'] ); | |
$args['echo'] = false; | |
// Grab the category dropdown | |
$tax_drop = wp_dropdown_categories( $args ); | |
// Add a label | |
$label = ( $args['label'] && !empty( $args['id'] ) ) ? '<label for="' . esc_attr( $args['id'] ) . '">' . esc_attr( $args['label'] ) . '</label>' : ''; | |
// Wrap it up | |
$class = $args['wrap_class'] ? ' class="' . esc_attr( $args['wrap_class'] ) . '"' : ''; | |
$tax_drop = ( $args['wrap'] && !empty( $tax_drop ) ) ? '<' . esc_attr( $args['wrap'] ) . $class . '>' . $label . $tax_drop . '</' . esc_attr( $args['wrap'] ) . '>' : $tax_drop; | |
// Return it or echo it back | |
if( $echo ) { | |
echo $tax_drop; | |
} else { | |
return $tax_drop; | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
Great! thank you for sharing. |
This comment has been minimized.
This comment has been minimized.
Hey @lw-na you can use the Either by adding it to the arguments passed in the custom function when it's called: $args = array(
'show_option_none' => 'Please select',
'taxonomy' => 'category'
);
jdn_get_custom_taxonomy_dropdown( $args ); OR, if you want this to be the default, you can update the defaults in the function: // Taxonomy dropdown arguments
$defaults = array(
'show_option_none' => 'Please Select',
'taxonomy' => false, // required, the default here is a failsafe
'post_type' => false, // pass a value if you want to
'echo' => false, // true to echo, false for return
'label' => false, // false or pass a string for the label
'query_var' => false, // pass the query variable for the selected dropdown value
'id' => '', // set this and the default category 'name' argument
'wrap' => 'div', // the wrapper element. set to false to skip it.
'wrap_class' => 'select-wrap', // The custom wrapper class, set to false to skip it
);
$args = wp_parse_args( $args, $defaults ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Very useful, thank you!
I had to query only post with
post_status='publish'
so I had to the$clauses['where']
this parameterNot sure if it’s the best solution but it works!