web-dev-qa-db-de.com

So schließen Sie Seiten aus den Suchergebnissen aus

Ich wollte pages aus den Suchergebnissen ausschließen und habe viele Möglichkeiten gefunden, dies zu tun. Ich habe mich gefragt, warum !is_admin() oder is_main_query() verwendet wird und welcher Weg besser ist.

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

Beachten Sie, dass, wenn wir verwenden:

$query->set( 'post_type', 'post' );

dann überschreiben wir alle durchsuchbaren Beitragstypen, nicht nur den Beitragstyp page.

In einigen Fällen ist das in Ordnung, und wir haben einige Ihrer pre_get_posts-Snippets verwendet, die unseren Anforderungen entsprechen.

Aber manchmal wollen wir es nicht so fest machen. Hier diskutieren wir solche Szenarien.

Verwenden des Filters register_post_type_args.

Wenn der Beitragstyp nicht angegeben ist, werden bei der Suche nach WP_Query alle durchsuchbaren Beitragstypen verwendet, und zwar :

$in_search_post_types = get_post_types( array('exclude_from_search' => false) );

Wenn wir einen Beitragstyp registrieren, können wir den Parameter exclude_from_search auf false setzen, um ihn von der Suche auszuschließen.

Wir können es für die Einrichtung des Post-Typs page ändern mit:

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

Mehr über register_post_type()hier .

Beispiele

In den folgenden Beispielen wird der Seitenzugriffstyp mithilfe der obigen Filterung von der Suche ausgeschlossen:

  • Hauptabfragesuche im Frontend mit

    https://example.tld?s=testing
    
  • Sekundäre Abfrage wie:

    $query = new WP_Query( [ 's' => 'testing' ] );
    
  • Sekundäre Abfrage wie:

    $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'any' ] );
    

Einige Hinweise zu Abfragen mit voreingestellten Beitragstypen:

Betrachten wir Fälle, in denen die Post-Typen behoben sind, wie:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page', 'post'] ] );

Wenn der Beitragstyp durch einen Array $post_type festgelegt ist, können wir den 'page' herausfiltern

if( is_array( $post_type )  && count( $post_type ) > 1 )
{
    $post_type = array_filter( 
        $post_type, 
        function( $item ) { return 'page' !== $item; } 
    );
}

Wenn wir keinen direkten Zugriff auf dieses Array haben, könnten wir z. pre_get_posts, um die 'Seite' mit Hilfe der get/set -Methoden von WP_Query aus dem Post-Typ-Array zu entfernen. Hier ist ein Beispiel für die Hauptsuchabfrage im Frontend:

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

} );

Warum haben wir hier die Arrayanzahl> 1 überprüft?

Das liegt daran, dass wir darauf achten sollten, 'page' aus Beispielen wie den folgenden zu entfernen:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [ 'page' ] ] );

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page' ] );

als leeres Array oder als leere Zeichenfolge für den Beitragstyp:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => [] ] );

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => '' ] );

wird auf den Beitragstyp 'post' zurückgreifen.

Beachten Sie, dass:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => 'page, post' ] );

wird nicht unterstützt, da der resultierende Beitragstyp 'pagepost' wäre.

In diesen Fällen, in denen wir keinen direkten Zugriff auf die WP_Query -Objekte haben, können wir die Abfrage mit Tricks wie 'post__in' => [] oder 1=0 in der Suche unterbrechen, wenn eine WHERE-Abfrage ausgeführt wird, oder sogar mit dem posts_pre_query-Filter oder mit erweiterten Methoden spielen. Darüber gibt es auf dieser Site viele Antworten. Das und das ist das, woran ich mich im Moment erinnere.

Der null Fall:

 $query = new WP_Query( [ 's' => 'testing', 'post_type' => null ] );

greift auf 'any' Beitragstypen zurück:

Ich hoffe es hilft!

PS:

Beachten Sie auch die Inkonsistenz in Ihren Snippets, da Sie beide haben

add_filter('pre_get_posts','search_filter');   

und

add_action('pre_get_posts','search_filter');   

Es wird als eine Aktion betrachtet, aber es macht keinen Unterschied, da Aktionen hinter den Kulissen als Filter verpackt sind.

4
birgire

pre_get_posts wird sowohl im Admin als auch im Frontend ausgeführt. Sie können es verwenden, um Beiträge zu filtern, die den Admin-Benutzern angezeigt werden, sowie Frontend-Ergebnisse. Durch das Hinzufügen von ! is_admin() wird sichergestellt, dass sich dieser Code nur auf das Frontend auswirkt.

is_main_query() stellt sicher, dass Sie nur die Abfrage für die Posts beeinflussen, nicht beispielsweise die Menüelemente in der Navigationsleiste oder eine Liste der Posts in der Seitenleiste. Es wird empfohlen, das zu verwenden.

Lassen Sie mich wissen, wenn dies nicht klar ist,

3
Ben Casey