Query to get result by Title or Meta along with tax_query parameter

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

  1. Change the add_filter( 'get_meta_sql', function( $sql ) use ( $title ) to add_filter( 'get_meta_sql', function( $sql, $queries, $type ) use ( $title ).

  2. Change the return $sql; }); to return $sql; }, 10, 3); (i.e. let the above closure accepts 3 parameters).

  3. Then change the if( 0 != $nr++ ) return $sql; to if( '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;
}