I am going to try and explain this the best that I can but I find it rather complex and out of my comfort zone. I have spent a week trying to find the answers online and I have hit a snag.
Backstory : I am building a tool that can filter custom post types by all of the custom fields attached to that custom post type, and also custom fields attached to other custom post types via the "Relationship" field of ACF (advanced custom fields). You can see it here : roottiedev.wpengine.com/strains
I have most everything working so far. The user can use the filter sidebar to select any of the fields and values they want to filter by. The javascript applies these fields to the URL string. ex) https://roottiedev.wpengine.com/strains?feelings_$_feeling=Happy
Because some custom fields are 2 dimensional (repeater or group fields in ACF) I have to use the above example, with a $ between the parent key and child key.
There is a rewrite ever since wordpress 4.8.3 where ACF tells you that you have to change the _$ to a _%. You can see the documentation here : (scroll down to point 4.) https://www.advancedcustomfields.com/resources/query-posts-custom-fields/
This all works, as long as I am using one field. It seems like the second I try to do multiple fields, or the second I try to use a field that doesn't use a 'meta_compare' of "LIKE" (for example, on the filters you will see I have two slider select bars that say "THC %" and "CBD %") that everything fails. The sliders don't use a compare of "LIKE" they are using either ">=" or "<=" instead.
My $_GET in my functions.php to rewrite the "add_action('pre_get_posts', 'my_pre_get_posts');" seems to work just fine using IF statements, but again, could also be the cause of it not working on multiple fields.
Ok, so hopefully that explains what I am attempting to do. Here is the code snippets that I feel are relevant.
// START THE CUSTOM LOOP
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action('genesis_loop', 'roottie_strains', 10);
function roottie_strains () {
// grab the meta query relation. Will all fields be 'and' or 'or'
$meta_query = array( 'relation' => 'AND' );
// loop through $meta_query to grab key and values
foreach ( wp_parse_args( $query_string ) as $key => $value ) {
$meta_query[] = array( 'key' => $key, 'value' => $value );
}
$args = array(
'posts_per_page' => 18,
'post_type' => 'strains',
'post_status' => 'publish',
'order' => ASC,
'paged' => get_query_var( 'paged' ),
'meta_query' => $meta_query,
);
// https://www.advancedcustomfields.com/resources/query-posts-custom-fields/
// THIS IS APPARENTLY NEEDED DUE TO CHANGES IN ESC_SQL() FOR WORDPRESS 4.8.3. WE CHANGE _$_ TO _%_ INSTEAD
add_filter('posts_where', 'my_posts_where');
function my_posts_where( $where ) {
/* if( isset($_GET['feelings_$_feeling']) ) {
$where = str_replace("meta_key = 'feelings_$", "meta_key LIKE 'feelings_%", $where);
return $where;
} */
$rootkeys[] = $_GET;
global $wpdb; //TESTING
foreach($rootkeys as $rootkey) {
foreach($rootkey as $key => $value) {
$partialkey = explode("$",$key);
$keya = $partialkey[0];
$keyb = 'meta_key = \''.$keya.'$';
$keyc = 'meta_key LIKE \''.$keya.'%'; //this = was LIKE, should it be?
// $where = str_replace($keyb, $keyc, $where);
$where = str_replace($keyb, $keyc, $wpdb->remove_placeholder_escape($where));
}
}
return $where;
}
Then, for the functions.php file, here is my rewrite :
// GET URL STRING FOR FILTERING ON ANY POST. FILTER WP_QUERY BY URL STRING EX roottie.com/brands?field=blue
add_action('pre_get_posts', 'my_pre_get_posts');
function my_pre_get_posts( $query ) {
// do not modify queries in the admin
//
if( is_admin() ) {
return $query;
}
// only modify queries for 'strains' post type
//
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'strains' ) {
// allow the url to alter the query
if( isset($_GET['strain_type']) ) {
$query->set('meta_key', 'strain_type');
$query->set('meta_value', $_GET['strain_type']);
}
if( isset($_GET['feelings_$_feeling']) ) {
$query->set('meta_key', 'feelings_$_feeling');
$query->set('meta_value', $_GET['feelings_$_feeling']);
}
if( isset($_GET['medical_use_$_medical']) ) {
$query->set('meta_key', 'medical_use_$_medical');
$query->set('meta_value', $_GET['medical_use_$_medical']);
}
if( isset($_GET['sflavours_$_sflavour']) ) {
$query->set('meta_key', 'sflavours_$_sflavour');
$query->set('meta_value', $_GET['sflavours_$_sflavour']);
}
if( isset($_GET['thc_min']) ) {
$query->set('meta_key', 'thc_min');
$query->set('meta_value', $_GET['thc_min']);
$query->set('meta_compare', '>=');
$query->set('meta_type', 'NUMERIC');
}
if( isset($_GET['thc_max']) ) {
$query->set('meta_key', 'thc_max');
$query->set('meta_value', $_GET['thc_max']);
$query->set('meta_compare', '<=');
$query->set('meta_type', 'NUMERIC');
}
if( isset($_GET['cbd_min']) ) {
$query->set('meta_key', 'cbd_min');
$query->set('meta_value', $_GET['cbd_min']);
$query->set('meta_compare', '>=');
$query->set('meta_type', 'NUMERIC');
}
if( isset($_GET['cbd_max']) ) {
$query->set('meta_key', 'cbd_max');
$query->set('meta_value', $_GET['cbd_max']);
$query->set('meta_compare', '<=');
$query->set('meta_type', 'NUMERIC');
}
}
// return
return $query;
}
Any help or point in the right direction would be huge! I can't figure out if the issue is with the "compare" or if the issue is in looping through all of the fields in the meta_query re-write for version 4.8.3 (where we take feelings_$ and rewrite it to feelings_%
For an example of an output, if we use this url :
https://roottiedev.wpengine.com/strains?thc_min=5&thc_max=20&cbd_min=5&cbd_max=20&feelings_$_feeling=Uplifted
The is the dump of the wp_query
SELECT SQL_CALC_FOUND_ROWS wp_roottie_posts.ID FROM wp_roottie_posts INNER JOIN wp_roottie_postmeta ON ( wp_roottie_posts.ID = wp_roottie_postmeta.post_id ) WHERE 1=1 AND ( ( wp_roottie_postmeta.meta_key = 'thc_max' AND CAST(wp_roottie_postmeta.meta_value AS SIGNED) <= '20' ) ) AND wp_roottie_posts.post_type = 'strains' AND ((wp_roottie_posts.post_status = 'publish')) GROUP BY wp_roottie_posts.ID ORDER BY wp_roottie_posts.post_date ASC LIMIT 0, 18