it-swarm.com.de

Entfernen Sie die Homepage-Abfrage

Ich habe eine Homepage mit der Vorlage home.php, die 2 Seitenleisten mit Widgets enthält.

Bei der Hauptabfrage werden immer noch die Standard-10-Posts abgerufen. Da ich diese jedoch nicht anzeige, möchte ich die Abfrage für die Datenbank vollständig entfernen. Gegebenenfalls reicht eine leere Post-Schleife aus, da ich die Hauptschleife in meiner home.php-Vorlage nicht verwende.

Wie würde ich das machen? Ich könnte pre_get_posts verwenden, um die Abfrage zu minimieren und zu reduzieren, aber ich habe trotzdem eine sehr schnelle Abfrage. Wie kann ich sie vollständig entfernen?

8
Tom J Nowell

Der posts_request Filter

Durchsuchen Sie den WP_Query wir finden diesen Teil von Interesse:

if ( !$q['suppress_filters'] ) {
    /**
     * Filter the completed SQL query before sending.
     *
     * @since 2.0.0
     *
     * @param array    $request The complete SQL query.
     * @param WP_Query &$this   The WP_Query instance (passed by reference).
     */
      $this->request = apply_filters_ref_array( 'posts_request', 
          array( $this->request, &$this ) );
   }

   if ( 'ids' == $q['fields'] ) {
       $this->posts = $wpdb->get_col( $this->request );
       $this->posts = array_map( 'intval', $this->posts );
       $this->post_count = count( $this->posts );
       $this->set_found_posts( $q, $limits );
       return $this->posts;
   }

Wir versuchen möglicherweise, die Hauptstartanforderung über den Filter posts_request zu entfernen. Hier ist ein Beispiel:

add_filter( 'posts_request', function( $request, \WP_Query $q )
{
    // Target main home query
    if ( $q->is_home() && $q->is_main_query() )
    {
        // Our early exit
        $q->set( 'fields', 'ids' );

        // No request
        $request = '';
    }

    return $request;    

}, PHP_INT_MAX, 2 );

wo wir den 'fields' => 'ids' zum vorzeitigen beenden erzwingen.

Der posts_pre_query Filter (WP 4.6+)

Wir könnten auch den neuen posts_pre_query verwendensrc Filter verfügbar in WordPress 4.6+

add_filter( 'posts_pre_query', function( $posts, \WP_Query $q )
{
    if( $q->is_home() && $q->is_main_query() )
    {
        $posts = [];
        $q->found_posts = 0;
    }
    return $posts;
}, 10, 2 );

Dieser Filter ermöglicht es, die üblichen Datenbankabfragen zu überspringen, um stattdessen eine benutzerdefinierte Posts-Injection zu implementieren.

Ich habe dies gerade getestet und festgestellt, dass dies im Gegensatz zum posts_request-Ansatz keine klebrigen Beiträge verhindert.

Schauen Sie sich das Ticket # 36687 für weitere Informationen und das Beispiel dort von @boonebgorges an.

7
birgire

Hier ist ein guter Trick, den ich von @birgire gelernt habe. Wir können die Hauptabfrage anhalten, indem wir AND where 0=1 an die WHERE-Klausel der SQL-Abfrage anhängen. Dies kann immer noch zu einer Datenbankabfrage führen, verhindert jedoch mit Sicherheit, dass die Hauptabfrage Beiträge abfragt

add_filter( 'posts_where', function ( $where, \WP_Query $q )
{
    if (    $q->is_home()
         && $q->is_main_query()
    ) {
        $where .= ' AND where 0 = 1';
    }

    return $where;
}, 10, 2 ); 

Sie können auch einfach versuchen, die WHERE -Klausel durch where 0 = 1 zu ersetzen.

$where = ' where 0 = 1';

anstatt

$where .= ' AND where 0 = 1';

Leider habe ich keine Zeit, etwas zu testen, aber dies sollte ein guter Ausgangspunkt sein

2
Pieter Goosen

Als referenz, vor: 45q, nach: 42q

Der Code ist dem von @birgire verwendeten Code sehr ähnlich

function _tomjn_home_cancel_query( $query, \WP_Query $q ) {
    if ( !$q->is_admin() && !$q->is_feed() && $q->is_home() && $q->is_main_query() ) {
        $query = false;
        $q->set( 'fields', 'ids' );
    }
    return $query;
}
add_filter( 'posts_request', '_tomjn_home_cancel_query', 100, 2 );
2
Tom J Nowell