I've got a custom post type called course
. Within a course post, I have a number of custom fields, specifically (all AFC select dropdowns): course_or_project
, time_to_complete_project
, time_to_complete_course
and difficulty
. I also have a taxonomy called course_project_category
.
My aim is to be able to create a number of dropdown/sliders, build a URL by reading the values of said dropdowns/sliders and on click of a search button, use the query string I've put together (jQuery) to filter just the right posts. This functionality is all working. Well... sometimes the results are a little confused i.e. only filtering by some of the parameters.
On to the code.
I've added a function in to expose my custom fields:
function my_pre_get_posts( $query ) {
// do not modify queries in the admin
if( is_admin() ) {
return $query;
}
// only modify queries for 'course' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) {
// allow the url to alter the query
if( isset($_GET['course_or_project']) ) {
$query->set('meta_key', 'course_or_project');
$query->set('meta_value', $_GET['course_or_project']);
}
if( isset($_GET['time_to_complete_project']) ) {
$query->set('meta_key', 'time_to_complete_project');
$query->set('meta_value', $_GET['time_to_complete_project']);
}
if( isset($_GET['time_to_complete_course']) ) {
$query->set('meta_key', 'time_to_complete_course');
$query->set('meta_value', $_GET['time_to_complete_course']);
}
if( isset($_GET['difficulty']) ) {
$query->set('meta_key', 'difficulty');
$query->set('meta_value', $_GET['difficulty']);
}
}
// return
return $query;
}
add_action('pre_get_posts', 'my_pre_get_posts');
Querying the taxonomy appears to work out-of-the-box.
So an example of my completed URL might be:
http://localhost:3000/courses/?course_project_category=jokes&course_or_project=project&difficulty=easy&time_to_complete_project=15
My results are a mixed bag at this point.
From the above query, I've returned 2 posts which mostly match my criteria but as a specific example, one post has a time_to_complete_project
value as 30
even though the query specified 15
.
I cannot figure this out. I can see the parameters are all there as expected through Chrome dev tools:
Any ideas?!
Update
Here's a new approach I have that is working (but is lacking validation and sanitation):
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'field_1' => 'course_or_project',
'field_2' => 'difficulty',
'field_3' => 'time_to_complete_project',
'field_4' => 'time_to_complete_course'
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) {
return;
}
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'course' ) {
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// update meta query
$query->set('meta_query', $meta_query);
}
}
meta_query
. Your code will never work if you have more than onemeta_key
. Also, you should never ever use unsanitized and non validated values from a$_GET
variable (or any other type of input)