Devo usar Pre Get Posts ou WP_Query

29

Eu tenho a seguinte consulta que eu chamo no meu modelo taxonomy.php via query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

Esta função funciona perfeitamente. No entanto, depois de ler o codex para as postagens de consulta, ele mencionou pre_get_posts como a maneira preferida de alterar a consulta padrão. Os pre_get_posts seriam mais eficientes que minha função wp_query abaixo?

Em caso afirmativo, como eu construiria os pre_get_posts e passaria minha variável e consulta abaixo?

function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
   global $wp_query; 
   $wp_query = new WP_Query();
   $args = array( 
      'post_type' => $posttype, 
      'post_status' => array($poststatus), 
      'orderby' => 'rand', 
      'posts_per_page' => 30, 
      'meta_query' => array( 
         array( 
            'key' => 'wpcf-paid', 
            'value' => array($paidvalue), 
            'compare' => 'IN', 
            ) 
      ), 
      'tax_query' => array( 
         'relation' => 'AND', 
         array( 
            'taxonomy' => $taxtype, 
            'field' => 'slug', 
            'terms' => $geo 
         ), 
         array( 
            'taxonomy' => 'brands', 
            'field' => 'slug', 
            'terms' => $brands 
         ) 
      ) 
   ); 

   return $wp_query->query($args); 
} 
user1609391
fonte

Respostas:

14

pre_get_postsexecutará a mesma consulta, portanto, ambos levarão o mesmo tempo. Mas, se você utilizar a pre_get_postsação, salvará uma ou mais consultas SQL. No momento, o WordPress está executando a consulta padrão e, em seguida, você executa sua consulta com esta função que substitui os resultados da consulta padrão (a consulta padrão resultante é inútil). Abaixo está como você pode mover o seu $argspara

function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {

    // filter your request here.
    if($query->is_category) {

        $args = array(
            'post_type' => $posttype,
            'post_status' => array($poststatus),
            'orderby' => 'rand',
            'posts_per_page' => 30,
            'meta_query' => array(
                array(
                    'key' => 'wpcf-paid',
                    'value' => array($paidvalue),
                    'compare' => 'IN',
                )
            ),
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => $taxtype,
                    'field' => 'slug',
                    'terms' => $geo
                ),
                array(
                    'taxonomy' => 'brands',
                    'field' => 'slug',
                    'terms' => $brands
                )
            )
        );
        $query->query_vars = $args;
    }
}
add_action('pre_get_posts', 'custom_pre_get_posts');
SR
fonte
Muito obrigado pela resposta. É muito útil. Uma pergunta rápida. Eu coloquei a função no meu arquivo function.php do tema. Eu executo essa função custom_pre_get_posts ($ query) no meu taxonomy.php. No taxonomy.php, configurei as variáveis ​​$ posttype, $ post_status, $ geo, $ brands, $ taxtype e executei dois loops alterando essas variáveis. Existe uma maneira de passar variável para a função acima de taxonomy.php? Quando tento custom_pre_get_posts ($ query, 'dealer', 'publish', '1', $ taxtype, $ geo, $ brands); Recebo o argumento ausente 2 a 7 para custom_pre_get_posts (). Eu assumo devido a add_action ???
user1609391
1
Suponho que você alterou o custom_pre_get_posts para aceitar os argumentos restantes. Sim, você está recebendo um erro devido a add_action. add_action chama essa função com argumento único (ou seja, $ query), você deve atribuir valores padrão a outros argumentos para evitar erros de argumento ausentes. like ($ posttype = null, $ poststatus = null ...) para que possa ser chamado adequadamente por add_action.
MR
MR Obrigado pela resposta. Li sobre adicionar ação e vejo que deveria atribuir um número de prioridade e argumentos. Então mudei minha ação add para <code> add_action ('pre_get_posts', 'custom_pre_get_posts', 10,7); </code> Então, na minha página taxonomy.php, eu <code> do_action ('pre_get_post', $ query, ' revendedores ',' publicar ',' 1 ', $ tipo de imposto, $ área geográfica, $ marcas); </code>. Mas ainda estou recebendo o mesmo erro. Eu não tinha certeza de onde colocar os valores padrão. Eu tentei o google, mas não consegui encontrar uma referência. Você pode me dar um pouco mais de informação sobre como lidar com isso?
user1609391
Obrigado pela resposta e exemplo. Mas acho que posso estar tentando usar pre_get_posts quando deveria estar fazendo uma nova consulta wordpress. Eu estava tentando salvar uma consulta, mas no meu caso talvez não seja possível. A razão é que todos os argumentos que você definiu no parâmetro, eu queria passar para a função do meu arquivo taxonomy.php. Portanto, $ paidvalue = ”1” pode ser 1 ou 0, dependendo da condição que estou executando no taxonomy.php. Parece que pre_get_posts acima é acionado quando a página é carregada, mesmo que eu não chame a função no meu arquivo taxonomy.php. Estou vendo isso correto?
user1609391
3
Esta resposta não faz sentido, como está atualmente escrita. Você efetivamente substituirá qualquer valor dentro do $wp_queryobjeto e as coisas falharão completamente. Além de que é simplesmente não é verdade que pre_get_postsirá executar uma consulta adicional ...
kaiser
10

Resposta tardia, pois a resposta mais votada interromperá sua consulta e simplesmente não é verdadeira em alguns pontos importantes.

O principal WP_Query e seus filtros

Primeiro, o WordPress usa internamente query_posts()(um invólucro fino WP_Queryque não deve ser usado em temas ou plugins) para fazer um WP_Query. Isso WP_Queryestá atuando como o loop / consulta principal. Essa consulta será executada por vários filtros e ações até que a string de consulta SQL real seja criada. Um deles é pre_get_posts. Outros são posts_clauses, posts_whereetc., que também permitem interceptar o processo de criação da string de consulta.

Uma análise aprofundada do que acontece dentro do núcleo

O WordPress executa a wp()função (in wp-includes/functions.php), que chama $wp->main()( $wpé um objeto da classe WP, que é definido em wp-includes/class-wp.php). Isso diz ao WordPress para:

  1. Analise o URL em uma especificação de consulta usando WP->parse_request()+ mais sobre isso abaixo.
  2. Defina todas as variáveis ​​is_ usadas pelos Tags Condicionais usando $wp_query->parse_query()( $wp_queryé um objeto de class WP_Query, definido em wp-includes/query.php). Observe que, apesar do nome dessa função, nesse caso WP_Query->parse_query, na verdade, não fazemos nenhuma análise para nós, pois isso é feito antecipadamente WP->parse_request().
  3. Converta a especificação da consulta em uma consulta ao banco de dados MySQL e execute a consulta ao banco de dados para obter a lista de postagens, na função WP_Query-> get_posts (). Salve as postagens no objeto $ wp_query para serem usadas no loop do WordPress.

Codex Fonte

Conclusão

Se você realmente deseja modificar a consulta principal, pode usar uma grande variedade de filtros. Basta usar $query->set( 'some_key', 'some_value' );a mudança de dados lá ou utilização $query->get( 'some_key' );para recuperar dados para fazer verificações condicionais. Isso evitará que você faça uma segunda consulta, pois está alterando apenas a consulta SQL.

Se você precisar fazer uma consulta adicional , vá com um WP_Queryobjeto. Isso adicionará outra consulta ao banco de dados.

Exemplo

Como as respostas sempre funcionam melhor com um exemplo, você tem um exemplo muito bom (adereços para Brad Touesnard), que simplesmente estende o objeto principal e, portanto, é bastante reutilizável (faça dele um plugin):

class My_Book_Query extends WP_Query
{
    function __construct( $args = array() )
    {
        // Forced/default args
        $args = array_merge( $args, array(
            'posts_per_page' => -1
        ) );

        add_filter( 'posts_fields', array( $this, 'posts_fields' ) );

        parent::__construct( $args );
    }

    public function posts_fields( $sql )
    {
        return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
    }
}

Em seguida, você pode executar sua segunda consulta / adicional como você pode ver no exemplo a seguir. Não se esqueça de redefinir sua consulta posteriormente.

$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
    while ( $book_query->have_posts() )
    {
        $book_query->the_post();
        # ...do stuff...
    } // endwhile;
    wp_reset_postdata();
} // endif;
kaiser
fonte