Qual é o método correto para determinar 'is_front_page' ao usar filtros como 'pre_get_posts' e 'posts_where'?

4

No meu site, vários filtros devem ser aplicados se o usuário estiver visualizando a página inicial estática. Meu entendimento é que is_front_page() deve determinar se esse é realmente o caso.

No entanto, sempre que uso a função, descubro que às vezes ela retorna true (por exemplo, posts_orderby ), mas retorna false (por exemplo, pre_get_posts , posts_fields , posts_join e posts_where ) . Independentemente do resultado, eu sempre recebo o seguinte aviso -

  

Tentando obter propriedade de não objeto em {my_path} \ wp-includes \ query.php na linha 4373

O método que contém a linha ofensiva é WP_Query::is_front_page() -

public function is_front_page() {
    // most likely case
    if ( 'posts' == get_option( 'show_on_front') && $this->is_home() )
        return true;
    /** The offending line */ elseif ( 'page' == get_option( 'show_on_front') && get_option( 'page_on_front' ) && $this->is_page( get_option( 'page_on_front' ) ) )
        return true;
    else
        return false;
}

Para combater esse problema, criei minha própria função, como abaixo, mas parece "sujo" ter que fazer isso. Então, minha pergunta é assim - existe uma maneira melhor de fazer isso?

function fgw_is_front_page($q){

    if(!is_a($q, 'WP_Query'))
        return false;

    return (get_option('show_on_front') == 'page' && get_option('page_on_front') && $q->get('page_id') == get_option('page_on_front'));

}

Editar

Após uma investigação mais aprofundada, parece que a linha incorreta é realmente 4369 (wp-includes / querey.php) - $page_obj = $this->get_queried_object();

$page_obj está sendo retornado como null , o que significa que a verificação de $q->is_front_page() falha. Isso parece errado, e a menos que alguém seja capaz de explicar como isso poderia de alguma forma ser um comportamento esperado, vou olhar para a abertura de um ticket no Trac.

Atualizar

Agora alterei a função acima. O uso do segundo argumento passado para todos os filtros que estou usando (a instância WP_Query), como mencionado por @birgire , permitiu que eu eliminasse o global.

No entanto, tomando o exemplo abaixo, ainda estou recebendo o aviso acima mencionado (e resultado de false ) ao verificar $q->is_front_page() -

add_filter('posts_fields','fgw_index_posts_fields', 10, 2);
function fgw_index_posts_fields($fields, $q){

    global $wpdb;

    if(!is_admin() && is_main_query() && (is_home() || $q->is_front_page($q)))
        $fields.= $wpdb->prepare(', %1$s.name as category_name', $wpdb->terms);

    return $fields;

}

Substituir $q->is_front_page() por fgw_is_front_page($q) funciona, mas novamente parece sujo ter que usar uma solução personalizada quando aparentemente já existe uma.

    
por David Gard 14.05.2015 / 11:54

1 resposta

5

Com relação aos ganchos posts_orderby , posts_where , posts_join e posts_clauses , o objeto \WP_Query atual está disponível por meio do argumento de entrada segundo .

Estas são as partes relevantes da classe \WP_Query :

$orderby = apply_filters_ref_array( 'posts_orderby', array( $orderby, &$this ) );
$where   = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );
$join    = apply_filters_ref_array( 'posts_join', array( $join, &$this ) );
$clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &$this ) );

todos usando a função apply_filters_ref_array e &$this é a atual \WP_Query instance. O Codex diz o seguinte sobre esta função:

  

Esta função é idêntica a apply_filters , mas os argumentos foram passados   para as funções conectadas a $ tag são fornecidas usando uma matriz.

Você pode acessar o segundo argumento com, por exemplo:

add_filter( 'posts_where', function( $where, \WP_Query $q )
{
    if( $q->is_front_page() ) <-- This method won't work here with a static front-page!!!
    {
        // ...
    }
}, 10, 2 );

para que você não precise depender do objeto global $wp_query .

Após rastrear isso dentro de WP_Query , descobrimos o motivo pelo qual chamar o método is_front_page() não funciona dentro desses retornos de chamada do filtro. Existe um problema no método is_page() que tenta usar o método get_queried_object() que ainda não tem um objeto para retornar.

O método is_home() funciona, por outro lado, e não está chamando o método is_page() .

Atualização:

Parece haver pelo menos dois tíquetes do Trac, # 27015 e #21790 , relacionado com este problema.

Em # 27015, há um patch sugerido por @mattonomics, que modifica o queried_object object dentro do método parse_query() .

Então, por que não tentar essas modificações no nosso caso, mas através do parse_query hook:

/**
 * A workaround for the is_front_page() check inside pre_get_posts and later hooks.
 *
 * Based on the patch from @mattonomics in #27015
 *
 * @see http://wordpress.stackexchange.com/a/188320/26350
 */

add_action( 'parse_query', function( $q )
{
    if( is_null( $q->queried_object ) && $q->get( 'page_id' ) )
    {
        $q->queried_object    = get_post( $q->get( 'page_id' ) );
        $q->queried_object_id = (int) $q->get( 'page_id' );
    }
} );

Devemos poder adicionar mais alterações desta forma, a partir desse patch.

    
por birgire 14.05.2015 / 12:16