substitua a classe WP_Query na consulta principal

4

Para um projeto, precisei modificar strongmente o comportamento de WP_Query. Então, o que eu fiz foi estender o WP_Query basicamente assim:

class eacf_shared_query extends \WP_Query {

    function query( $query ) {

        // do things before ...

        $posts = parent::query($query);

        // do things after ...

        return $posts;
    }

Isso funciona como um encanto para todas as minhas consultas personalizadas para as quais agora uso minha classe estendida, mas não consigo encontrar uma maneira de inserir isso no main_query.

Então minha pergunta é: Existe alguma maneira conhecida de substituir / estender a classe WP_Query no arquivo main_query?

Eu achei que o acima era a única solução e não consegui mais usar os filtros fornecidos dentro da classe original porque:

  • Parece não haver um par de filtros garantido para ser executado antes e depois da consulta, então não posso conseguir com segurança uma construção como no exemplo acima.
  • A lógica "fazer as coisas depois de" contém chamadas aninhadas para WP_Query (), que facilmente acabam em um loop de consulta, se eu usar filtros.
  • Os filtros SQL parecem não ser poderosos o suficiente para criar uma única consulta buscando todos os posts (como construir uma consulta UNION). Estou precisando mesclar postagens de diferentes blogs em uma consulta e parece que isso não pode ser alcançado com filtros como posts_clauses_request ou query .
por s1lv3r 16.10.2013 / 13:45

2 respostas

4

Ok, é factível, mas poderia potencialmente estragar algumas coisas, por isso é por sua conta e risco, mas então é tudo:)

Estou tentando fazer isso para usar uma classe de extensão GeoQuery para ordenar eventos por distância de algum local.

A maneira mais simples de fazer isso é:

add_action( 'after_setup_theme', 'alt_query_class', 1, 0 );
function alt_query_class() {
    if ( ! is_admin() && $GLOBALS[ 'wp_query' ] instanceof WP_Query ) {
         $GLOBALS[ 'wp_the_query' ] = new WP_Query_Extended();
         $GLOBALS[ 'wp_query' ] = $GLOBALS[ 'wp_the_query' ];
    }
}

Na sua classe de consulta estendida, basta fazer o que você tem acima, mas se sua funcionalidade adicional for algo que não é desejável para todas as consultas, será necessário fazer alguma lógica de configuração / desmontagem porque estamos substituindo cada instância WP_Query com o novo.

No meu caso, usei o filtro pre_get_posts com uma prioridade atrasada para verificar se precisava adicionar minha funcionalidade ou não depois que todas as manipulações de consulta foram feitas.

class WP_Query_Extended extends WP_Query {

    function query( $args = array() ) {

        // setup functions
        add_filter( 'pre_get_posts', array( $this, 'check_setup_needed' ), 1000 );

        // run the query
        parent::query( $args );

        // tear down functions
        $this->teardown();
    }

    function check_setup_needed( $query ) {

        // test setup criteria
        if ( $query->get( 'somevar' ) ) {
            $this->setup();
        }

        return $query;
    }

    function setup() {
        // add any filters etc... here
    }

    function teardown() {
        // remove filters etc... here
        remove_filter( 'pre_get_posts', array( $this, 'check_setup_needed' ) );
    }

}

ATUALIZAÇÃO:

Há uma grande pegadinha com isso - se alguém usa query_posts() , por exemplo. pode estar em um plug-in ou se você estiver escrevendo um plug-in, talvez um tema, então essa função redefine o $wp_query global de volta para uma WP_Query instance e não há nenhum filtro com o qual alterá-lo novamente.

Se você realmente precisa fazer um query_posts() (não deveria!), você pode fazer $wp_query->query( $args ) .

    
por sanchothefat 29.01.2014 / 14:39
1

Sugiro que você conecte um filtro ao posts_results hook para substituir $ posts pelo resultado de sua consulta personalizada. No entanto, esse método produz processamento redundante à medida que a consulta principal é processada primeiro e, em seguida, os resultados são "sobrescritos" com seus resultados personalizados.

    
por Dominic Yun 30.10.2013 / 14:13

Tags