Sur mon site, plusieurs filtres doivent être appliqués si l'utilisateur visualise la page d'accueil statique. Je crois comprendre que is_front_page()
devrait déterminer si tel est bien le cas.
Cependant, chaque fois que j'utilise la fonction, je constate que parfois, elle renvoie true
(par exemple, posts_orderby
) mais la plupart du temps, elle renvoie false
(par exemple, pre_get_posts
, posts_fields
, posts_join
et posts_where
). Indépendamment du résultat, je reçois toujours la notification suivante -
Essayer d'obtenir la propriété de non-objet dans {mon chemin}\wp-includes\query.php à la ligne 4373
La méthode contenant la ligne fautive est 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;
}
Pour lutter contre ce problème, j'ai créé ma propre fonction, comme ci-dessous, mais cela semble "sale" d'avoir dû le faire. Ma question est donc la suivante: existe-t-il une meilleure façon de procéder?
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'));
}
Après une enquête plus poussée, il semble que la ligne incriminée soit en réalité 4369 (wp-includes/querey.php) - $page_obj = $this->get_queried_object();
$page_obj
est retourné sous la forme null
, ce qui signifie que la vérification de $q->is_front_page()
échoue. Cela semble faux et, à moins que quiconque soit en mesure d'expliquer comment un tel comportement pourrait être attendu, je vais ouvrir un ticket sur Trac.
J'ai maintenant modifié la fonction ci-dessus. Utiliser le second argument transmis à tous les filtres que j'utilise (l'instance WP_Query), comme indiqué par @birgire , m'a permis de supprimer le filtre global.
Cependant, en prenant l'exemple ci-dessous, je reçois toujours l'avis susmentionné (et le résultat de false
) lors de la vérification de $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;
}
Remplacer $q->is_front_page()
par fgw_is_front_page($q)
fonctionne, mais encore une fois, il est déplacé de devoir utiliser une solution personnalisée alors qu’il en existe apparemment une qui existe déjà.
En ce qui concerne les hooks posts_orderby
, posts_where
, posts_join
et posts_clauses
, l'objet \WP_Query
actuel est disponible via l'argument second input.
Voici les parties pertinentes de la 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 ) );
tous en utilisant apply_filters_ref_array
function et &$this
est l'instance actuelle de \WP_Query
. Le Codex dit ce qui suit à propos de cette fonction:
Cette fonction est identique à
apply_filters
, mais les arguments transmis aux fonctions rattachées à $ tag sont fournis à l'aide d'un tableau.
Vous pouvez accéder au deuxième argument avec par exemple:
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 );
vous n'avez donc pas à vous fier à l'objet global $wp_query
.
Après avoir tracé cette trace dans WP_Query
, nous avons trouvé la raison pour laquelle l'appel de la méthode is_front_page()
ne fonctionne pas dans ces rappels de filtre. Il y a un problème dans la méthode is_page()
qui tente d'utiliser la méthode get_queried_object()
qui n'a toujours pas d'objet à renvoyer.
La méthode is_home()
fonctionne en revanche et n'appelle pas la méthode is_page()
.
Il semble y avoir au moins deux billets Trac, # 27015 et # 21790 , liés à ce problème.
Dans # 27015, il y a une suggestion patch by @mattonomics, qui modifie l'objet queried_object
dans la méthode parse_query()
.
Alors, pourquoi ne pas essayer ces modifications dans notre cas, mais via le crochet parse_query
à la place:
/**
* 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' );
}
} );
Nous devrions pouvoir ajouter d'autres modifications de cette façon, à partir de ce correctif.
au lieu de
$query->is_front_page()
essayez d'utiliser
$query->get('page_id') == get_option('page_on_front')
(Dans le contexte:)
function custom_pre_get_posts( $query ) {
if ( $query->get('page_id') == get_option('page_on_front') ) {
// do stuff
}
}
add_action('pre_get_posts', 'custom_pre_get_posts');
Cette solution est à partir d'ici: https://core.trac.wordpress.org/ticket/21790#comment:11