template_include for search.php makes WordPress think its on the home page

Your problem is that you are not resetting all the needed query variables, like WP_Query::$is_page, WP_Query::$is_single and WP_Query::$is_archive.

Also note that 'pre_get_posts' is fired for all queries, the main and the secondaries, so you should check that you are working on the main query.

Finally, when you get data from $_GETyou should sanitize it before to use it, a good way is to use filter_input() or filter_input_array().

Your method should appear something like this:

public static function pre_get_posts($query)
{
    $data = filter_input_array(INPUT_GET, array(
        'tag-search' => FILTER_SANITIZE_STRING,
        'terms'      => FILTER_SANITIZE_STRING,
        'method'     => FILTER_SANITIZE_STRING,
    ));
    if( $query->is_main_query() && !empty($data['tag-search']) && !empty($data['terms']) ) {
        $query->init(); // this resets ALL vars
        $query->is_search = true;
        // set tax query array
        $tax_query = array(
            'taxonomy' => $data['tag-search'],
            'field'    => 'slug',
            'terms'    => explode(',', $data['terms']),
        );
        // is AND method?
        if( strtolower( $data['method'] ) === 'and' ) {
            $tax_query['operator'] = 'AND';
        }
        // set tax query
        $query->set( 'tax_query', array($tax_query) );
    }
}

Doing so you do not need to filter the template (so you can remove your template_redirect() method): search.php will be loaded by WordPress because it will correctly recognize the query as a search.


PS: 'pre_get_post' is an action, not a filter, so you don’t need to return the query neither if you modify it.

Leave a Comment