Je voulais exclure pages
des résultats de la recherche et j'ai trouvé plusieurs façons de le faire. Je me demandais pourquoi utiliser !is_admin()
ou is_main_query()
et quelle serait la meilleure solution.
add_filter('pre_get_posts','search_filter');
function search_filter($query) {
if ($query->is_search) {
$query->set('post_type', 'post');
}
return $query;
}
add_filter('pre_get_posts','search_filter');
function search_filter($query) {
if ( !is_admin() && $query->is_search) {
$query->set('post_type', 'post');
}
return $query;
}
add_action('pre_get_posts','search_filter');
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
if ($query->is_search) {
$query->set('post_type', 'post');
}
}
}
Notez que lorsque nous utilisons:
$query->set( 'post_type', 'post' );
alors nous ignorons tous les types de publication interrogeables, pas seulement le type de publication page
.
Cela peut convenir dans certains cas, et nous avons fini d'utiliser certains de vos extraits de code pre_get_posts
qui répondent à nos besoins.
Mais parfois, nous ne voulons pas résoudre le problème de cette façon. Nous discutons ici de ce genre de scénarios.
Utilisation du filtre register_post_type_args.
Lorsque le type de publication n'est pas spécifié, la recherche WP_Query
utilise les types de publication pouvant faire l'objet d'une recherche, à savoir :
$in_search_post_types = get_post_types( array('exclude_from_search' => false) );
Lorsque nous enregistrons un type de publication, nous pouvons définir le paramètre exclude_from_search
sur false pour l'exclure de la recherche.
Nous pouvons le modifier pour la configuration du type de poste page
avec:
add_filter( 'register_post_type_args', function( $args, $name )
{
// Target 'page' post type
if( 'page' === $name )
$args['exclude_from_search'] = true;
return $args;
}, 10, 2 );
En savoir plus sur register_post_type()
here .
Exemples
Voici des exemples où le type de publication de page serait exclu de la recherche, en utilisant le filtrage ci-dessus:
Recherche de requête principale sur le front-end avec
https://example.tld?s=testing
Requête secondaire comme:
$query = new WP_Query( [ 's' => 'testing' ] );
Requête secondaire comme:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => 'any' ] );
Quelques notes sur les requêtes avec types de post prédéfinis:
Prenons les cas où les types de publication sont fixes, comme:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page', 'post'] ] );
Si le type de publication est défini par un tableau $post_type
, nous pouvons filtrer le 'page'
avec
if( is_array( $post_type ) && count( $post_type ) > 1 )
{
$post_type = array_filter(
$post_type,
function( $item ) { return 'page' !== $item; }
);
}
Si nous n’avons pas un accès direct à ce tableau, nous pourrions utiliser par exemple pre_get_posts
pour supprimer la 'page' du tableau post type, à l'aide des méthodes get
/set
de WP_Query
. Voici un exemple de requête de recherche principale sur le front-end:
add_action( 'pre_get_posts', function search_filter( \WP_Query $query )
{
if( ! $query->is_search() || ! $query->is_main_query() || ! is_admin() )
return;
$post_type = $query->get( 'post_type' );
if( is_array( $post_type ) && count( $post_type ) > 1 )
{
$post_type = array_filter(
$post_type,
function( $item ) { return 'page' !== $item; }
);
$query->set('post_type', $post_type );
}
} );
Pourquoi avons-nous vérifié le nombre de tableaux> 1 ici?
C'est parce que nous devrions faire attention à supprimer 'page'
des exemples tels que:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page' ] ] );
$query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page' ] );
sous forme de tableau vide ou de chaîne vide, pour le type de publication:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => [] ] );
$query = new WP_Query( [ 's' => 'testing', 'post_type' => '' ] );
retombera dans le type de message 'post'
.
Notez que:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page, post' ] );
n'est pas pris en charge, car le type de message résultant serait 'pagepost'
.
Dans ces cas, où nous n'avons pas d'accès direct aux objets WP_Query
, nous pourrions arrêter la requête avec des astuces telles que 'post__in' => []
ou 1=0
dans la partie de requête WHERE de la recherche ou même jouer avec le filtre posts_pre_query
ou utiliser des méthodes plus avancées. Il y a beaucoup de réponses sur ce site à ce sujet. Ceci et ceci est ce que je me rappelle pour le moment.
Le cas null
:
$query = new WP_Query( [ 's' => 'testing', 'post_type' => null ] );
retombe à 'any'
types de poste:
J'espère que ça aide!
PS:
Notez également l’incohérence dans vos extraits, car vous avez les deux
add_filter('pre_get_posts','search_filter');
et
add_action('pre_get_posts','search_filter');
C'est considéré comme une action, mais cela ne fera aucune différence, car les actions sont encapsulées sous forme de filtres, en arrière-plan.
pre_get_posts
fonctionnera dans admin ainsi que dans le frontend, vous pouvez l'utiliser pour filtrer les publications qui apparaissent aux utilisateurs admin ainsi que les résultats du frontend. En ajoutant ! is_admin()
, vous vous assurez que ce code n’affecte que le client.
is_main_query()
veillera à ce que vous n'affectiez que la requête relative aux publications, pas par exemple les éléments de menu dans la barre de navigation, ou une liste de publications dans la barre latérale. Il est recommandé de l'utiliser.
Faites-moi savoir si ce n'est pas clair,