Last active
February 27, 2023 13:44
-
-
Save joshuadavidnelson/4e82bbd506b776534a6f to your computer and use it in GitHub Desktop.
Filter wp_dropdown_categories by post type.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
} |
Great! thank you for sharing.
How to place text "Please Select" at very first element of dropdown list.
Hey @lw-na you can use the show_option_none
parameter from wp_dropdown_categories
(see the WP documentation here), as the arguments for the jdn_get_custom_taxonomy_dropdown
function get passed to the core function.
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
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!