If you instantiate WP_Query
with arguments, as in your second example, then the query is performed right away, and setting new arguments will not change the results.
$q = new WP_Query( [ 'post_type' => 'post' ] );
$q->set( 'tax_query', [] ); // Too late.
If you instantiate WP_Query
without arguments, like this:
$q = new WP_Query();
Then the query is not performed until $q->get_posts()
is run. This means that you can set query vars after the object is created:
$q = new WP_Query();
$q->set( 'post_type', 'post' );
$q->set( 'tax_query', [] );
$q->get_posts();
while ( $q->have_posts() ) {
// etc..
}
There’s nothing special about tax_query
when it comes to setting arguments like this.
The pre_get_posts
hook is fired inside WP_Query::get_posts()
, before the query itself is performed, so in that hook there’s no reason you can’t set tax_query
:
add_action(
'pre_get_posts',
function( $query ) {
$query->set( 'tax_query', [] );
}
);
The one thing that might trip you up is that any given query might already have a tax_query
, and by setting it yourself you could be removing that original query. The way around this is to retrieve the original query, and then add yours.
add_action(
'pre_get_posts',
function( $query ) {
$tax_query = $query->get( 'tax_query', [] ); // Make sure we have an array as the default.
$new_tax_query = [
[
'taxonomy' => 'post_format',
'field' => 'slug',
'operator' => 'IN',
'terms' => [ 'post-format-link' ],
],
$tax_query,
];
$query->set( 'tax_query', $new_tax_query );
}
);