¿Cuál es el método correcto para determinar 'is_front_page' cuando se usan filtros como 'pre_get_posts' y 'posts_where'?

4

En mi sitio, se deben aplicar varios filtros si el usuario está viendo la página de inicio estática. Según entiendo, is_front_page() debe determinar si ese es realmente el caso.

Sin embargo, siempre que uso la función, encuentro que a veces devuelve true (por ejemplo, posts_orderby ), pero principalmente devuelve false (por ejemplo, pre_get_posts , posts_fields , posts_join y posts_where ) . Sin embargo, independientemente del resultado, siempre recibo el siguiente aviso:

  

Intentando obtener una propiedad de no objeto en {mi_ruta} \ wp-includes \ query.php en la línea 4373

El método que contiene la línea infractora es 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 combatir este problema, he creado mi propia función, como se muestra a continuación, pero parece "sucio" haber tenido que hacerlo. Así que mi pregunta es: ¿hay una mejor manera de hacer esto?

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

Después de una investigación adicional, parece que la línea infractora es en realidad 4369 (wp-includes / querey.php) - $page_obj = $this->get_queried_object();

$page_obj se está devolviendo como null , lo que significa que la verificación de $q->is_front_page() falla. Esto parece incorrecto y, a menos que alguien sea capaz de explicar cómo podría ser este el comportamiento esperado, buscaré abrir un ticket en Trac.

Actualizar

Ahora he enmendado la función anterior. El uso del segundo argumento pasado a todos los filtros que estoy usando (la instancia WP_Query), como lo menciona @birgire , me ha permitido eliminar el global.

Sin embargo, tomando el siguiente ejemplo, todavía recibo la notificación mencionada (y el resultado de false ) al 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;

}

Reemplazar $q->is_front_page() con fgw_is_front_page($q) funciona, pero de nuevo se siente sucio tener que usar una solución personalizada cuando parece que ya existe una.

    
pregunta David Gard 14.05.2015 - 11:54

1 respuesta

5

En cuanto a los ganchos posts_orderby , posts_where , posts_join y posts_clauses , el objeto \WP_Query actual está disponible a través del segundo argumento de entrada.

Estas son las partes relevantes de la clase \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 utilizando la función apply_filters_ref_array y &$this es la instancia actual \WP_Query . El Codex dice lo siguiente acerca de esta función:

  

Esta función es idéntica a apply_filters , pero los argumentos pasados   Las funciones enganchadas a $ tag se suministran mediante una matriz.

Puedes acceder al segundo argumento con, por ejemplo:

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 no tenga que confiar en el objeto global $wp_query .

Después de rastrear esto dentro de WP_Query , hemos encontrado la razón por la que llamar al método is_front_page() no funciona dentro de estas devoluciones de llamada de filtro. El problema reside en el método is_page() que intenta utilizar el método get_queried_object() que aún no tiene un objeto para devolver.

El método is_home() funciona por otro lado, y no está llamando al método is_page() .

Actualización:

Parece que hay al menos dos tickets de Trac, # 27015 y #21790 , relacionado con este problema.

En # 27015 hay un parche sugerido por @mattonomics, que modifica el queried_object objeto dentro del método parse_query() .

Entonces, ¿por qué no probar estas modificaciones en nuestro caso, sino a través del enlace parse_query ?

/**
 * 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' );
    }
} );

Deberíamos poder agregar más cambios de esta manera, desde ese parche.

    
respondido por el birgire 14.05.2015 - 12:16

Lea otras preguntas en las etiquetas