Remova a consulta da página inicial

8

Eu tenho uma página inicial exibindo o home.phpmodelo, contendo 2 barras laterais com widgets.

A consulta principal ainda recebe as 10 postagens padrão, mas como não as estou exibindo, gostaria de eliminar completamente a consulta que está sendo feita no banco de dados. Se necessário, um loop de postagem vazio fará como eu não estiver usando o loop principal no meu home.phpmodelo.

Como eu faria isso? Eu poderia usar pre_get_postspara minimizar e reduzir a consulta, mas isso ainda me deixa com uma consulta muito rápida, como a elimino totalmente?

Tom J Nowell
fonte
1
Esta questão parece valer a pena ser lida. Mas se você me perguntasse, eu usaria meu próprio modelo e o definiria como página inicial estática nas configurações, porque, embora fosse possível, simplesmente não vale a pena. Leitura mais interessante aqui . Ou tudo isso ou perdi completamente o ponto de sua pergunta.
900 de N00b

Respostas:

7

O posts_requestfiltro

Percorrendo a página WP_Query, encontramos essa parte de 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;
   }

Podemos tentar eliminar a solicitação inicial principal através do posts_requestfiltro. Aqui está um exemplo:

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

onde forçamos a 'fields' => 'ids'saída antecipada.

O posts_pre_queryfiltro (WP 4.6+)

Também poderíamos usar o novo filtro posts_pre_querysrc disponível no 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 );

Esse filtro permite ignorar as consultas usuais do banco de dados para implementar uma injeção de postagens personalizada.

Acabei de testar isso e notei que isso não impedirá postagens pegajosas, ao contrário da posts_requestabordagem.

Confira o ticket nº 36687 para obter mais informações e o exemplo de @boonebgorges.

Birgire
fonte
Muito parecido com o que acabei de escrever, mas não localizei a parte dos IDs dos campos, o que provocou outras 2 consultas, obrigado!
Tom J Nowell
1
ok, ótimo, às vezes me lembro como seria bom ter uma maneira fácil de sair mais WP_Querycedo, por exemplo, através de um argumento como 'skip_query' => trueou mesmo através de um filtro, mas então eu percebo o quão facilmente isso poderia atrapalhar sites na Internet, então Várias maneiras ;-) @TomJNowell
birgire
Existe um filtro split_the_querylogo abaixo das linhas, faça exatamente o mesmo, mas será que isso não reduz o número de consultas!
Sumit
Grande solução, mesmo que eu perdi 'fields' => 'ids', e eu usá-lo muito ;-)
Pieter Goosen
2

Aqui está um truque interessante que aprendi com o @birgire; podemos interromper a consulta principal anexando AND where 0=1à WHEREcláusula da consulta SQL. Isso ainda pode resultar em uma consulta de banco de dados, mas certamente impedirá a consulta principal de consultar postagens

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

Você também pode apenas tentar substituir a WHEREcláusula porwhere 0 = 1

$where = ' where 0 = 1';

ao invés de

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

Infelizmente, não tenho tempo para testar nada, mas esse deve ser um bom ponto de partida

Pieter Goosen
fonte
Parece que é o mais próximo que posso chegar do que pedi ou, pelo menos, a consulta mais otimizada; considerarei isso ao investigar se a consulta pode ser erradicada.
Tom J Nowell
+1 por compartilhar essa ideia. Mas eu testei e reduzi o tempo em 2 ms :)
Resume
Eu gostaria de me lembrar de onde aprendi, mas isso também é usado pelo núcleo ;-) Eu acho que seria bom também ignorar os stickies $q->set( 'ignore_sticky_posts', true );por precaução.
22916 birgire
@birgire Ótimo local. Mesmo com a minha solução, você ainda receber stickies de volta da consulta principal ;-)
Pieter Goosen
2

Para referência, antes: 45q, depois: 42q

O código é muito semelhante ao código usado por @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 );
Tom J Nowell
fonte