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?
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 $_GET
vous 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.
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