web-dev-qa-db-fra.com

template_include for search.php fait que Wordpress pense que c'est sur la page d'accueil

J'ai une fonctionnalité personnalisée de recherche de balises, qui permet aux gens de rechercher plusieurs balises pour retourner des publications pertinentes. Dites qu'ils veulent voir les messages étiquetés à la fois 'Wordpress' et 'Tutorials'. J'utilise le filtre template_include, comme suit:

public static function template_redirect( $template ) {
    if( isset($_GET['tag-search']) )
    {
        $template = locate_template( array(
            'search.php',
            'archive.php',
            'index.php'
        ));
    }
    return $template;
}

la variable tag-search contient le nom de la taxonomie, je vérifie si elle est définie, indiquant ainsi qu'une recherche est en cours.

À ce stade, template se résout en search.php, comme il se doit. Donc c'est bien.

Dans l'action pre_get_posts, j'ajoute un tax_query pour modifier les publications renvoyées uniquement aux balises sélectionnées, et je règle is_search sur true et is_home sur false. Voici mon action pre_get_posts:

public static function pre_get_posts($query) {
    if( !isset($_GET['tag-search']) || !isset($_GET['terms'])  ) return $query;

    if( strtolower( $_GET['method'] ) == 'and' )
    {
        $query->set( 'tax_query', array(
            array(
                'taxonomy' => $_GET['tag-search'],
                'field' => 'slug',
                'terms' => explode(',', $_GET['terms']),
                'operator' => 'AND'
            )
        ) );
    }
    else
    {
        $query->set( 'tax_query', array(
            array(
                'taxonomy' => $_GET['tag-search'],
                'field' => 'slug',
                'terms' => explode(',', $_GET['terms'])
            )
        ) );
    }
    $query->is_search = true;
    $query->is_home = false;
    return $query;
}

Cependant, lorsque j'effectue la recherche, la classe body est 'home' et tous les conditionnels is_home et is_front_page sont true , ce qu'ils ne devraient pas être, car je viens de préciser que je veux que ce soit une recherche. modèle non?

Je sais que cela peut être fait - lorsque j'ajoute &s à la chaîne de requête, cela fonctionne comme il se doit - même si c'est un peu moche de cette façon. Des idées?

3
Shawn Wernig

Votre problème est que vous ne réinitialisez pas toutes les variables de requête nécessaires, telles que WP_Query::$is_page, WP_Query::$is_single et WP_Query::$is_archive.

Notez également que 'pre_get_posts' est déclenché pour toutes les requêtes, principale et secondaire, vous devez donc vérifier que vous travaillez sur la requête principale.

Enfin, lorsque vous obtenez des données à partir de $_GETvous devriez les désinfecter avant de les utiliser, un bon moyen consiste à utiliser filter_input() ou filter_input_array() .

Votre méthode devrait ressembler à ceci:

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) );
    }
}

Pour ce faire, vous deveznot/ filtrer le modèle (afin de pouvoir supprimer votre méthode template_redirect()): search.php sera chargé par WordPress car il reconnaîtra correctement la requête en tant que recherche.


PS: 'pre_get_post' est unaction, pas un filtre, donc vousne pas/ n'avez pas à renvoyer la requête si vous la modifiez.

6
gmazzap

Essayez ce qui suit:

public static function pre_get_posts($query) {
    if( !isset($_GET['tag-search']) || !isset($_GET['terms'])  ) return $query;
        if ( ! is_admin() && $query->is_main_query() ) {
        if( strtolower( $_GET['method'] ) == 'and' )
        {
            $query->set( 'tax_query', array(
                array(
                    'taxonomy' => $_GET['tag-search'],
                    'field' => 'slug',
                    'terms' => explode(',', $_GET['terms']),
                    'operator' => 'AND'
                )
            ) );
        }
        else
        {
            $query->set( 'tax_query', array(
                array(
                    'taxonomy' => $_GET['tag-search'],
                    'field' => 'slug',
                    'terms' => explode(',', $_GET['terms'])
                )
            ) );
        }
        $query->set('s', '' );
        $query->is_search = true;
        $query->is_home = false;
    }
    return $query;
}

J'ai ajouté des vérifications supplémentaires et le 's' d'une manière moins laide

0
chifliiiii