The Why part
In the core is_search()
function there’s a check if the global $wp_query
is set:
global $wp_query;
if ( ! isset( $wp_query ) ) {
_doing_it_wrong( __FUNCTION__,
__( 'Conditional query tags do not work before the query is run.
Before then, they always return false.' ), '3.1.0' );
return false;
}
Note that you’re unsetting it with:
$wp_query = null;
just before you create a new WP_Query
subquery, that calls is_search()
when pre_get_posts
fires.
That’s when the _doing_it_wrong()
is activated.
Workaround
Always try to use the main query, instead of extra WP_Query
sub-queries if possible, to avoid running extra database queries.
To target the main search query in the front-end, we can use:
add_action('pre_get_posts', function( \WP_Query $q ) {
if (
! is_admin() // Only target the front-end
&& $q->is_main_query() // Target the main query
&& $q->is_search() // Target a search query
) {
// do stuff
}
});