I’ve managed to workaround the problem. He’re the solution for further reference.
1) I have only 1 query var now:
function return_vars( $vars ) {
$vars[] = 'filters';
return $vars;
}
2) My rewrite rules changed to:
add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/page/([0-9]{1,})/?', 'index.php?post_type=$matches[1]&filters=$matches[2]&paged=$matches[3]', 'top');
add_rewrite_rule( 'my-base/filters/([^\/]*)/([^&]*)/?', 'index.php?post_type=$matches[1]&filters=$matches[2]', 'top');
Rule 1: handles pagination
Rule 2: handles main page only
They have to be in this order.
3) Then, I filter the filters string more or less in this way
function my_pre_get_posts( $query ) {
$filters = get_query_var('filters');
// if no filter or if filters are odd, then return
if(!$filters || count(explode("https://wordpress.stackexchange.com/", $k4w_filters)) % 2 != 0) return;
// this is a global array with my 2 tax slugs in it
global $CUSTOM_TAXES_S;
$chunks = array_chunk(explode("https://wordpress.stackexchange.com/", $filters), 2);
$filter_data = array_combine(array_column($chunks, 0), array_column($chunks, 1));
// filter data, populate tax_data and field_data for queries
foreach($filter_data as $key => $value) {
if(in_array($key, $CUSTOM_TAXES_S)) {
$tax_data[$key] = $value;
} else {
$field_data[$key] = $value;
}
$query->set('debug_tax_data', $tax_data);
$query->set('debug_field_data', $field_data);
}
// if tax_data exist set tax_query
if($tax_data) {
foreach( $tax_data as $taxonomy => $slugs ) {
// append tax query
$tax_query[] = array(
'taxonomy' => get_tax_name($taxonomy), // that's a simple function that retrieves the taxonomy name from its slug
'field' => 'slug',
'terms' => explode(',', $slugs),
);
}
$query->set('tax_query', $tax_query);
}
// if field_data exist set meta_query
if($field_data) {
foreach( $field_data as $key => $value ) {
// append tax query
$meta_query[] = array(
'key' => $key,
'value' => explode(',',$value),
'compare' => 'IN',
);
}
$query->set('meta_query', $meta_query);
}
}
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
In this way I can even provide multiple terms for taxes, or values for fields, such as:
/my-base/filters/my-cpt/tax1/term1,term2/tax2/term1,term2/field1/val1,val2/goingon...
And it’ll work! With pagination too.
Obviously the code above works, but there has too be several checks to avoid issues and hacks (such as checking if a provided field name exists, or not, or if it’s in a filtrable-field list etcetera).
Hope this will help someone
🙂