web-dev-qa-db-fra.com

Comment exclure des pages des résultats de la recherche

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');
        }
    }
}
4
SilverLink

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.

4
birgire

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,

3
Ben Casey