Entfernen Sie die Homepage-Abfrage

8

Ich habe eine Homepage, auf der die home.phpVorlage angezeigt wird und die 2 Seitenleisten mit Widgets enthält.

Die Hauptabfrage zieht immer noch die Standard-10-Beiträge ein, aber da ich diese nicht anzeige, möchte ich die Abfrage, die an die Datenbank gesendet wird, vollständig entfernen. Bei Bedarf reicht eine leere Post-Schleife aus, da ich die Hauptschleife in meiner home.phpVorlage nicht verwende.

Wie würde ich das machen? Ich könnte pre_get_postsdie Abfrage minimieren und reduzieren, aber das lässt mich immer noch mit einer sehr schnellen Abfrage zurück. Wie kann ich sie vollständig entfernen?

Tom J Nowell
quelle
1
Diese Frage scheint lesenswert zu sein. Aber wenn Sie mich fragen würden, würde ich meine eigene Vorlage verwenden und sie aus den Einstellungen als statische Homepage festlegen, denn es wäre zwar möglich, aber es lohnt sich einfach nicht. Weitere interessante Lektüre hier . Entweder das alles oder ich habe den Punkt Ihrer Frage völlig verfehlt.
N00b

Antworten:

7

Der posts_requestFilter

Beim Durchblättern WP_Queryfinden wir 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 könnten versuchen, die Hauptanforderung über den posts_requestFilter zu eliminieren . 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 die 'fields' => 'ids'für die vorzeitige Ausfahrt erzwingen .

Der posts_pre_queryFilter (WP 4.6+)

Wir könnten auch den neuen posts_pre_querysrc- Filter verwenden, der in WordPress 4.6+ verfügbar ist

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_requestAnsatz keine klebrigen Pfosten verhindert .

Weitere Informationen und das Beispiel von @boonebgorges finden Sie im Ticket Nr . 36687.

Birgire
quelle
Sehr ähnlich zu dem, was ich gerade geschrieben habe, aber ich habe den Teil mit den Feld-IDs nicht erkannt, der weitere 2 Anfragen abgeschlagen hat, danke!
Tom J Nowell
1
ok toll, manchmal fällt mir ein, wie schön es wäre, eine einfache Möglichkeit zu haben, WP_Queryfrüh zu beenden , z. B. durch einen Streit wie 'skip_query' => trueoder sogar durch einen Filter, aber dann wird mir klar, wie leicht das Websites im Internet durcheinander bringen kann viele Möglichkeiten ;-) @TomJNowell
Birgire
Es gibt einen Filter split_the_querydirekt unter den Zeilen, machen Sie genau das Gleiche, aber ich frage mich, dass es die Anzahl der Abfragen nicht reduziert!
Summe
Tolle Lösung, auch wenn ich sie verpasst habe 'fields' => 'ids'und ich benutze sie oft ;-)
Pieter Goosen
2

Hier ist ein netter Trick, den ich von @birgire gelernt habe. Wir können die Hauptabfrage anhalten, indem wir AND where 0=1an die WHEREKlausel der SQL-Abfrage anhängen . Dies kann immer noch zu einer Datenbankabfrage führen, verhindert jedoch sicher, 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 WHEREKlausel durch zu ersetzenwhere 0 = 1

$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

Pieter Goosen
quelle
Das hört sich so an, als ob es dem am nächsten kommt, wonach ich gefragt habe, oder zumindest der am stärksten optimierten Abfrage. Ich werde dies berücksichtigen, wenn ich untersuche, ob die Abfrage selbst gelöscht werden kann
Tom J Nowell
+1 für das Teilen dieser Idee. Aber ich habe es getestet und es reduziert die Zeit um 2 ms :)
Summe
Ich wünschte, ich könnte mich daran erinnern, woher ich es gelernt habe, aber dies wird auch von Core verwendet ;-) Ich denke, es wäre schön, auch Stickies $q->set( 'ignore_sticky_posts', true );für alle Fälle zu ignorieren .
Birgire
@ Birgire Toller Ort. Selbst mit meiner Lösung erhalten Sie immer noch Stickies von der Hauptabfrage zurück ;-)
Pieter Goosen
2

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 );
Tom J Nowell
quelle