Rimuovere la query sulla home page


8

Ho una homepage che mostra il home.phpmodello, contenente 2 barre laterali con widget.

La query principale inserisce ancora i post standard 10, ma poiché non li sto visualizzando, mi piacerebbe eliminare completamente la query che viene effettuata nel database. Se necessario, un post loop vuoto farà come non sto usando il loop principale nel mio home.phpmodello.

Come lo farei? Potrei usare pre_get_postsper minimizzare e ridurre la query, ma ciò mi lascia ancora con una query molto veloce, come posso eliminarla del tutto?


1
Questa domanda sembra valere la pena di essere letta. Ma se me lo chiedessi, userei il mio modello e lo imposterei come home page statica dalle impostazioni, perché mentre sarebbe possibile, non ne vale la pena. Lettura più interessante qui . O tutto questo o ho completamente perso il punto della tua domanda.
N00b,

Risposte:


7

Il posts_requestfiltro

Sfogliando la WP_Querytroviamo questa parte di 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;
   }

Potremmo provare a eliminare la richiesta principale di casa attraverso il posts_requestfiltro. Ecco un esempio:

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

dove forziamo l' 'fields' => 'ids'uscita anticipata.

Il posts_pre_queryfiltro (WP 4.6+)

Potremmo anche usare il nuovo filtro posts_pre_querysrc disponibile 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 );

Questo filtro consente invece di saltare le normali query del database per implementare un'iniezione di post personalizzata.

Ho appena testato questo e ho notato che questo non impedirà i messaggi appiccicosi, al contrario posts_requestdell'approccio.

Controlla il biglietto # 36687 per maggiori informazioni e l' esempio lì da @boonebgorges.


Molto simile a quello che ho appena scritto, ma non ho individuato la parte ID dei campi, che ha eliminato altre 2 query, grazie!
Tom J Nowell

1
ok fantastico, a volte mi viene in mente quanto sarebbe bello avere un modo semplice per uscire WP_Querypresto, ad esempio attraverso un argomento simile 'skip_query' => trueo anche attraverso un filtro, ma poi mi rendo conto di quanto facilmente ciò possa rovinare i siti su Internet, in modo che molti modi ;-) @TomJNowell
birgire

C'è un filtro split_the_queryappena sotto le righe, fai esattamente lo stesso ma mi chiedo che non riduca il numero di query!
Vertice del

Ottima soluzione, anche io mi sono perso 'fields' => 'ids', e lo uso molto ;-)
Pieter Goosen

2

Ecco un trucco che ho imparato da @birgire, possiamo fermare la query principale aggiungendo AND where 0=1alla WHEREclausola della query SQL. Ciò potrebbe comunque comportare una query db, ma sicuramente interromperà la query principale dai messaggi di query

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

Puoi anche provare a sostituire la WHEREclausola conwhere 0 = 1

$where = ' where 0 = 1';

invece di

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

Sfortunatamente, non ho tempo di testare nulla, ma questo dovrebbe essere un buon punto di partenza


Sembra che sia il più vicino che posso ottenere a quello che ho chiesto, o almeno, la query più fortemente ottimizzata, la prenderò in considerazione mentre indagherò se la query stessa può essere sradicata
Tom J Nowell

+1 per condividere questa idea. Ma l'ho provato e riduce il tempo di 2 ms :)
Sumit

Vorrei ricordare da dove l'ho imparato, ma questo è anche usato dal core ;-) Penso che sarebbe bello ignorare anche gli sticky $q->set( 'ignore_sticky_posts', true );per ogni evenienza.
birgire

@birgire Ottimo posto. Anche con la mia soluzione, si ottiene ancora sticky dalla query principale ;-)
Pieter Goosen

2

Per riferimento, prima: 45q, dopo: 42q

Il codice è molto simile al codice utilizzato da @birgire

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 );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.