web-dev-qa-db-fra.com

get_post () vs global $ post ou $ GLOBAL ['post']

Je suis en train d'écrire un plugin de widget et j'ai besoin d'accéder à des informations postales.

J'ai vu des gens utiliser 3 approches différentes:

global $post;
if ( isset( $GLOBALS['post'] ) ) $post = $GLOBALS['post'];
$post = get_post();

Cet article explique la différence entre les deux premières solutions. Pouvez-vous s'il vous plaît confirmer qu'un appel à get_post() sans argument fait la même chose (pour lecture seule fins)?

En outre, en ce qui concerne la if ( isset( $GLOBALS['post'] ) ): Je suppose que cela signifie que post peut être indéfini. Quelqu'un pourrait-il expliquer dans quel contexte?

Dans mon cas, c'est un widget dans les pages (pas poster). Donc, est-il prudent de supposer que le code du widget étant exécuté après la boucle, post est toujours défini comme le contenu de la page dans de tels cas?

6
Mat

Essentiellement, à toutes fins techniques,

get_post() == $post == $GLOBALS['post']

Comme @tosho l'a déjà expliqué dans l'article lié , $post === $GLOBALS['post'], je ne vais donc pas entrer dans les détails.

Ce qui nous intéresse, c’est comment get_post() est le même. Pour cela, nous devrons examiner le code source . Comme vous pouvez le constater, notre réponse apparaît dans les deux premières lignes de la fonction lorsque nous ne transmettons rien à get_post()

if ( empty( $post ) && isset( $GLOBALS['post'] ) )
    $post = $GLOBALS['post'];

en ce qui concerne la if ( isset( $GLOBALS['post'] ) ): Je suppose que cela signifie que post peut être indéfini.

Oui, cela peut, et cela dépend du contexte. En outre, tout comme dans le monde, il peut être non défini, de manière délibérée ou non, ce qui peut avoir des effets catastrophiques. C’est pourquoi les globals sont si méchants à créer et à utiliser. Sans le savoir, l'utilisation de globales en tant que variables locales est la raison numéro un (IMO) pour les échecs de code inattendus et non corrigables.

Le $post global est défini par WP_Query::the_post(), mais il peut être modifié par n’importe quel code personnalisé. Ne vous fiez donc pas à cela, en particulier en dehors de la boucle.

est-il prudent de supposer que le code de widget est exécuté après la boucle

JAMAIS JAMAIS suppose rien. C'est la chose la plus dangereuse que vous puissiez faire lors du codage. Assumer simplement que quelque chose mène à de terribles bugs, des failles de sécurité, peut-être une fuite d’informations très personnelles qui pourraient vous conduire en prison, etc. Traitez tout ce que vous codez de manière à gérer en toute sécurité une chose ou un comportement spécifique en cas de défaillance, et alwyas code avec un état d'esprit selon lequel votre code va échouer et il sera piraté.

Encore une fois, les widgets peuvent être exécutés avant ou après la boucle, et même à l’intérieur de la boucle. Ne présumez donc pas qu’il se comportera d’une certaine manière.

S'il s'agit d'une vraie page (créée dans la section des pages finales), vous pouvez utiliser get_queried_object() pour obtenir l'objet de la page en cours. C'est beaucoup plus fiable que le $post global. Vous devriez prendre votre temps et lire cette réponse de @gmazzap à ma question ici

EDIT - Meilleure alternative à get_queried_object()

De votre commentaire à ma réponse

Je comprends que $post peut avoir été modifié avant d’y accéder. Mais n'est-ce pas également vrai pour $wp_query (modifié via des requêtes "personnalisées" ou "secondaires")? Si oui, ne devrais-je pas tester is_main_query() avant de m'appuyer sur get_queried_object()? Je suppose que la requête principale est basée sur l'URL demandée, non? Et si is_main_query() est false, que puis-je utiliser?

Très vrai, l'objet de requête principal est stocké dans la variable globale $wp_query. L'utilisation de $wp_query en tant que variable locale détruit l'objet de requête principal et le définit pour tout ce pour quoi vous utilisez l'objet global. De même, query_posts définit l'objet de requête principal sur la requête personnalisée actuelle, qui le casse également.

Il est vrai que l'objet interrogé repose sur l'intégrité de l'objet de requête principal, ce qui rend get_queried_object() vulnérable. En général, get_queried_object() est toujours beaucoup plus fiable que $post car toute requête personnalisée utilisant the_post() ou setup_postdata( $post ) définit le $post global sur la publication en cours dans la boucle en cours. Oublier de réinitialiser une requête personnalisée avec wp_reset_postdata() vous laissera le mauvais objet de publication dans $post.

En ce qui concerne get_queried_object(), si quelqu'un utilise toujours query_posts, c'est à lui de décider s'il souhaite en subir les conséquences.

J'aime l'idée que vous voudriez vraiment et que vous cherchiez vraiment des alternatives plus fiables à $postETget_queried_object(), cela ressort assez clairement de votre commentaire. Votre commentaire a en fait déclenché quelque chose sur lequel je travaillais il y a quelque temps et que j'ai complètement oublié, je pense surtout, y compris moi, nous oublions un global très important qui n'est jamais modifié (sauf par les filtres et les actions à l'intérieur de WP_Query lui-même), et ce global est $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] contient l'objet de requête principal réel. $GLOBALS['wp_query'] (AKA $wp_query) n'est qu'une copie de $GLOBALS['wp_the_query'].

Permet de regarder rapidement où cela est défini. Dans la version actuelle (Wordpress 4.4.2), vous trouverez le code suivant sur lines 291 - 304 dans `wp-settings.php

/**
 * WordPress Query object
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

Je ne connaissais pas bien WordPress à l'époque, mais cela a probablement été fait pour accommoder query_posts, car si vous regardez wp_reset_query() que vous devez utiliser après query_posts, il rétablit le $wp_query en $GLOBALS['wp_the_query'].

Tout cela signifie que, même si nous cassons l'objet de requête principal ($wp_query), nous avons toujours une copie entièrement vaild dans $GLOBALS['wp_the_query'].

Avec tout cela à l'esprit, si vous avez vraiment besoin d'un moyen fiable d'obtenir 99,99% l'objet interrogé actuel, ce serait $GLOBALS['wp_the_query']->get_queried_object(). Ce serait le moyen fiable ultime sans avoir à réexécuter vous-même la requête principale.

Avant de conclure, vous avez également parlé du contrôle is_main_query() (qui vérifie essentiellement si l'instance actuelle de WP_Query est égale à $GLOBALS['wp_the_query']). Dans un cas comme celui-ci, cela ne fonctionnerait pas vraiment, car cela renverrait simplement une valeur booléenne.

CONCLUSION - conclusion

Pour obtenir de manière fiable l’objet interrogé actuel sur une seule page d’article, ou sur une page unique ou une page d’archive, utilisez l’objet interrogé de la page $GLOBALS['wp_the_query'] global.

$GLOBALS['wp_the_query']->get_queried_object()
7
Pieter Goosen