From the documentation:
apply_filters_ref_array( 'get_meta_sql', string[] $sql, array $queries, string $type, string $primary_table, string $primary_id_column, object $context )
Filters the meta query’s generated SQL.
and
$type
(string) Type of meta. Possible values include but are not limited to ‘post’, ‘comment’, ‘blog’, ‘term’, and ‘user’.
So because a hook like the one above can run multiple times on a page, which means your filter/closure could be called multiple times for the same posts query (i.e. WP_Query
call), then you should do something like if ( 'post' === $type ) { modify the $sql['where'] }
to modify the WHERE
only if the meta type is exactly post
.
And basically after I tested your code, I noticed that the conditional if( 0 != $nr++ ) return $sql;
skipped modifying the post meta query and instead modified a term meta query, which means when the hook called your closure for the 1st time, it was for a term meta query.
Hence, that explains why the “whenever I use tax_query
, it is not working“.
How can you fix the issue
-
Change the
add_filter( 'get_meta_sql', function( $sql ) use ( $title )
toadd_filter( 'get_meta_sql', function( $sql, $queries, $type ) use ( $title )
. -
Change the
return $sql; });
toreturn $sql; }, 10, 3);
(i.e. let the above closure accepts 3 parameters). -
Then change the
if( 0 != $nr++ ) return $sql;
toif( 'post' !== $type || 0 != $nr++ ) return $sql;
Additional Code
You could use get_meta_sql
alone without having to use pre_get_posts
to add a filter for get_meta_sql
, like so:
add_filter( 'get_meta_sql', 'my_get_meta_sql', 10, 6 );
function my_get_meta_sql( $sql, $queries, $type, $primary_table, $primary_id_column, $context ) {
// Check that it's a post meta type and that the main query object is an instance of WP_Query.
if ( 'post' === $type && $context instanceof WP_Query &&
// And check that the _meta_or_title arg is set.
( $title = $context->get( '_meta_or_title' ) )
) {
global $wpdb;
$sql['where'] = 'YOUR CODE..';
}
return $sql;
}