UPDATE: Ma question initiale a été résolue, mais cela se transforme en une discussion valable sur pourquoi ne pas utiliser des variables globales, donc je mets à jour la question pour refléter cela. La solution était <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
comme @TomJNowell la suggéré.
UPDATE 2: Je lai maintenant fait exactement ce que je voulais. Mais jutilise toujours la portée globale et je serais heureux de trouver un meilleur moyen.
Jessaie de configurer tout un tas de variables globales pour les permaliens vers les catégories à utiliser à divers endroits de mon thème. La raison principale en est lutilisation à la fois dans la navigation principale, ainsi que dans une série de sous-navigations choisies en fonction de la catégorie dans laquelle se trouve le message actuel. Ce nest pas un thème Je vais publier pour une utilisation par dautres, mais est construit dans un but très spécifique.
Cest ainsi que je les crée actuellement (je nai collé que quelques-unes des variables).
function set_global_nav_var() { //proposal global $prop; // Get the ID of a given category $category_id_prop = get_cat_ID( "proposal" ); // Get the URL of this category $category_link_prop = get_category_link( $category_id_prop ); $prop = "<a href="" .esc_url( $category_link_prop ). "" title="Proposal">Proposal</a>"; //Calvinball global $cb; // Get the ID of a given category $category_id_cb = get_cat_ID( "calvinball" ); // Get the URL of this category $category_link_cb = get_category_link( $category_id_cb ); $cb = "<a href="" .esc_url( $category_link_cb). "" title="Calvinball">Calvinball</a>"; } add_action( "init", "set_global_nav_var" );
Je peux maintenant faire <?php global $prop; echo $prop; ?>
entre les 4 endroits qui vont et récupérer le lien complet pour le code. Lorsque cela change, je nai besoin de le changer quà un seul endroit. Je suis ouvert aux alternatives qui nimpliquent pas la portée globale.
Commentaires
- Quel lien cette déclaration fait-elle écho esc_url ($ category_link_prop); affiche ? Quel est votre lien attendu?
- Pourquoi nutiliseriez-vous pas simplement ‘ get_cat_ID (****) ‘ où que vous ayez prévu dutiliser la variable globale. Je doute quil y ait un avantage en termes de vitesse dans la façon dont vous le faites. Du point de vue de la lisibilité, ‘ get_cat_ID (****) ‘ gagne haut la main.
- Pouvez-vous reformuler? Jai lu votre question et je ‘ ne sais toujours pas ce que vous que vous voulez faire et pourquoi vous voulez le faire. Mon conseil général serait de ne pas utiliser de variables globales et de ne pas polluer la portée globale
- cela ressemble un peu à un Problème X / Y . Vous devriez peut-être revenir en arrière et expliquer exactement quel est le résultat souhaité. Je ‘ m certain ici ‘ est une solution bien plus élégante que de définir un tas de variables globales pour ensuite simplement coder en dur les références à celles-ci dans une navigation ailleurs
- créer une fonction qui affiche votre menu en fonction du contexte que vous lui transmettez, vous pouvez ainsi conserver toute la logique du menu et les variables associées encapsulées en un seul endroit.
Réponse
Bien que je déconseille fortement cela, et que cela pas accélérer les choses, votre utilisation est incorrect.
WordPress met déjà ces choses en cache dans le cache dobjets, vous navez pas besoin de stocker le résultat et de le réutiliser, WP le fait déjà .
Il est très probable que votre code sexécute plus lentement en raison de cette micro-optimisation, pas plus vite!
Comment utiliser Globals
Lorsque vous essayez dutiliser un global, vous devez dabord spécifier le mot-clé global
. Vous lavez spécifié ici lors de la définition de sa valeur, mais en dehors de cette portée, il doit être redéclaré en tant que variable de portée globale.
par exemple dans functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
Dans single.php
, cela ne fonctionnera pas:
echo $hello;
Parce que $hello
nest pas défini. Cependant, cela fonctionnera:
global $hello; echo $hello;
Bien sûr, vous ne devriez faire ni lun ni lautre. WordPress tente déjà de mettre en cache ces éléments dans le cache dobjets .
Inconvénients et dangers des variables globales
Vous ne verrez aucune augmentation de vitesse en faisant cela (vous pouvez voir une petite diminution de vitesse), tout ce que vous obtiendrez est une complexité supplémentaire et la nécessité de taper beaucoup de déclarations globales qui ne sont pas nécessaires.
Vous rencontrerez également dautres problèmes:
- code impossible à écrire des tests pour
- code qui se comporte différemment à chaque exécution
- conflits dans les noms de variables dun espace de nom partagé
- bogues accidentels dus à loubli de déclarer
global
- une absence totale de structure à votre stockage de données de codes
- et bien dautres
Que devriez-vous utiliser à la place?
Vous feriez mieux dutiliser des données structurées, telles en tant quobjets ou injection de dépendances, ou dans votre cas, un ensemble de fonctions.
Variables statiques
Variables statiques ne sont pas bons, mais considérez-les comme le cousin légèrement moins mauvais des variables globales.Les variables statiques sont aux variables globales, ce que le pain couvert de boue est au cyanure.
Par exemple, voici un moyen de faire quelque chose de similaire via des variables statiques, par exemple
function awful_function( $new_hello="" ) { static $hello; if ( !empty( $new_hello ) ) { $hello = $new_hello; } return $hello; } awful_function( "telephone" ); echo awful_function(); // prints telephone awful_function( "banana"); echo awful_function(); // prints banana
Singletons
Les singletons sont comme des variables statiques, sauf que la classe contient une variable statique avec une instance de cette classe . Elles sont tout aussi mauvaises que les variables globales, mais avec une syntaxe différente. Évitez-les.
WP_Cache, ce que vous avez essayé de faire mais WP le fait déjà
Si vous voulez vraiment gagner du temps en stockant les données quelque part pour les réutiliser, pensez à utiliser le système WP_Cache
avec wp_cache_get
etc par exemple
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
La valeur sera maintenant mise en cache pour la durée de vie de la requête par WordPress, apparaîtra dans les outils de débogage et si vous avez un cache dobjets, il « persistera à travers les requêtes
Note 1: Je noterais que certaines personnes essaient de conserver les données dans des variables globales à travers les requêtes, sans savoir que ce nest pas ainsi que PHP fonctionne . Contrairement à une application Node, chaque requête charge une nouvelle copie de lapplication, qui meurt ensuite lorsque la requête est terminée. Pour cette raison, les variables globales définies sur une requête ne survivent pas à la requête suivante.
Note 2: A en juger par la question mise à jour, vos variables globales ne vous donnent aucun gain de performance. Vous devriez simplement générer le HTML au fur et à mesure que vous en avez besoin et il fonctionnerait tout aussi vite, peut-être même un peu plus vite. Cest de la micro-optimisation.
Commentaires
- Je sais que ‘ est un peu fou pour utiliser le portée globale, mais la plupart, sinon toutes ces variables seront utilisées sur chaque page. Je ‘ suis ouvert à de meilleures idées. Je vais modifier la question pour rendre mon intention un peu plus claire. BTW cela fonctionne parfaitement bien quand je fais
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
selon votre suggestion. Merci! - Ah si ma solution fonctionne, pourriez-vous marquer comme acceptée? Vos variables globales sont tout aussi rapides que lappel dorigine, vous pouvez essayer dutiliser des fonctions à la place pour ne pas ‘ taper 2 lignes, mieux encore, un singleton, mieux encore, rendez tout cela dynamique et dans une partie de modèle incluse via get_template_part
- Marqué comme accepté comme cest ce que je fais maintenant, bien que je puisse suivre lune des stratégies suggérées par @MarkKaplun ci-dessous. Utiliser get_template_part () est une idée intéressante, mais je ‘ ne suis pas sûr de vouloir avoir un répertoire plein de fichiers courts comme ça …
- oooh non non vous ne ‘ t voulez un fichier pour chaque catégorie, vous ‘ ne voulez que celui qui saisit le nom de la catégorie actuelle et lutilise . Vous ne devriez pas ‘ avoir à coder quoi que ce soit, imaginez les tracas de tout coder en dur
- Jai mis le code dans mon child-functions.php qui est actif. Mais je ne peux pas accéder à la variable dans un fichier php-include que jappelle depuis un message généré par une base de données » normal « . Veuillez me conseiller, que dois-je faire de mal? (Je le définis comme global, bien sûr.)
Réponse
Nutilisez pas de variables globales , aussi simples que cela.
Pourquoi ne pas use globals
Parce que lutilisation de globals rend plus difficile la maintenance du logiciel sur le long terme.
- Un global peut être déclaré nimporte où dans le code, ou nulle part, il ny a donc aucun endroit où vous pouvez instinctivement regarder pour trouver un commentaire sur lutilisation du global
- En lisant le code, vous supposez généralement que les variables sont locales à la fonction et ne comprennent pas que la modification de leur valeur dans une fonction peut avoir un changement à l’échelle du système.
- Si elles ne gèrent pas d’entrée, les fonctions doivent renvoyer la même valeur / sortie lorsquelles sont appelés avec les mêmes paramètres. Lutilisation de globals dans une fonction introduit des paramètres supplémentaires qui ne sont pas documentés dans la déclaration de fonction .
- les globals nont pas de construction dinitialisation spécifique et par conséquent vous ne pouvez jamais être sûr quand vous pouvez accéder à la valeur du global, et vous nobtenez aucune erreur en essayant daccéder au global avant linitialisation .
- Quelquun dautre (un plugin peut-être) pourrait utiliser des globaux avec le même nom, ruiner votre code, ou vous ruiner en fonction de lordre dinitialisation.
Le cœur de WordPress a manière beaucoup trop grande utilisation des globaux. En essayant de comprendre comment fonctionnent les fonctions de base comme the_content
, vous vous rendez compte soudainement que la variable $more
nest pas locale mais globale et doit rechercher dans son ensemble des fichiers principaux pour comprendre quand est-il défini sur true.
Alors, que peut-on faire en essayant darrêter la copie & en collant plusieurs lignes de code au lieu de stocker le résultat de la première exécution dans un fichier global? Il existe plusieurs approches, fonctionnelles et POO.
La fonction édulcorant. Cest simplement un wrapper / macro pour enregistrer le copier / coller
// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; }
Les avantages sont quil existe maintenant une documentation sur ce que fait lancien global, et vous ont un point évident pour le débogage lorsque la valeur renvoyée nest pas celle que vous attendez.
Une fois que vous avez un édulcorant, il est facile de mettre en cache le résultat si nécessaire (ne le faites que si vous découvrez que cette fonction prend long à exécuter)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Cela vous donne le même comportement dun global mais avec lavantage davoir une initialisation assurée à chaque fois que vous y accédez.
Vous pouvez avoir des modèles similaires avec la POO. Je trouve que la POO najoute généralement aucune valeur aux plugins et aux thèmes, mais cest une discussion différente
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Cest un code plus maladroit, mais si vous ont plusieurs valeurs que vous souhaitez précalculer car elles sont toujours utilisées, cela peut être une solution. En gros, il sagit dun objet qui contient toutes vos valeurs globales de manière organisée. Pour éviter de faire dune instance de cet objet une instance globale (vous voulez une instance, sinon vous recalculez les valeurs) vous pouvez utiliser un motif singleton (certaines personnes soutiennent que cest une mauvaise idée, YMMV)
Je naime pas accéder directement à un attribut dobjet, donc dans mon code, il sera encore plus déformé
class notaglobal { var latestfoo2; __constructor() {} foo2($id) { if (!isset($this->latestfoo2)) { $a = foo1($id); $b = foo2($a); $this->latestfoo2= $b; } return $this->latestfoo2; } } $v = new notaglobal(); echo $v->foo2($cat_id);
Commentaires
- Sil vous plaît, don ‘ crie . Voulez-vous expliquer pourquoi et fournir une sorte de citation?
- Je pense que vous avez mal compris la réponse. Sil navait pas ‘ essayer de faire une optimisation précoce en stockant des valeurs dans des variables globales, son code aurait fonctionné. Le cri est dû au fait que suivre les principes de base du développement logiciel est quelque chose qui ne peut ‘ pas être suffisamment souligné. Les personnes qui ne comprennent pas ces principes de base (disponibles sur votre google local) ne doivent pas diffuser de code sur le net.
- IMO cest une réponse, les personnes qui viennent ici depuis Google devraient voir que cest une mauvaise idée pour même penser à utiliser des globaux tout de suite.
- Cela ‘ nest pas suffisant pour dire ne pas faire X, vous devez expliquer pourquoi ou vous ressemblez à vous ‘ si vous le dites sur un coup de tête
- @TomJNowell, je trouve drôle que je sois le seul à voter contre la question elle-même, car elle sortait évidemment du cadre de WASE. Je nai ‘ pas vu lintérêt de développer sur un sujet qui naurait pas du tout dû commencer ici.
Réponse
Votre question concerne le fonctionnement de php.
Prenez $ wpdb comme exemple
$ wpdb est une variable globale bien connue.
Savez-vous quand elle « sera déclarée et assignée avec des valeurs?
Chaque page chargée , oui, chaque fois que vous visitez votre site wordpress.
De même, vous devez vous assurer que les variables que vous souhaitez globaliser seront déclarées et attribuées avec les valeurs correspondantes à chaque page chargée.
Bien que je ne sois pas un concepteur de thème, je peux dire que after_setup_theme en est un crochet de temps. il ne sera déclenché que lorsque le thème est activé.
Si jétais vous, jutiliserai init ou dautres hooks. Non, si jétais vous, je nutiliserai pas du tout de variables globales …
Je ne suis vraiment pas doué pour expliquer les choses. Donc, vous devriez prendre un livre si vous voulez vous plonger dans PHP.
Réponse
Vous pouvez toujours utiliser un modèle singleton via des récupérateurs statiques.
<ul> <li><?php echo MyGlobals::get_nav_prop( "proposal" )[ "html" ]; ?></li> <li><?php echo MyGlobals::get_nav_prop( "calvinball", "html" ); ?></li> </ul> <?php if ( ! class_exists("MyGlobals") ): class MyGlobals { public $props; public function __construct(){ $this->props = array ( "proposal" => array( "title" => "Proposal", "text" => "Proposal" ), "calvinball" => array( "title" => "Calvinball", "text" => "Calvinball" ), ); } public function get_nav_prop ( $term, $prop = false ) { $o = self::instance(); if ( ! isset( $o->props[$term] ) ) { return falst; } if ( ! isset( $o->props[$term][ "html" ] ) ) { $id = get_cat_ID( $term ); $link = esc_url ( get_category_link( $id ) ); $title = $o->props[$term]["title"]; $text = $o->props[$term]["text"]; $o->props[$term]["html"] = "<a href="".$link."" title="".$title."">".$text."</a>"; $o->props[$term]["link"] = $link; $o->props[$term]["id"] = $id; } if($prop){ return isset($o->props[$term][$prop]) ? $o->props[$term][$prop] : null; } return $o->props[$term]; } // ------------------------------------- private static $_instance; public static function instance(){ if(!isset(self::$_instance)) { self::$_instance = new MyGlobals(); } return self::$_instance; } } endif; // end MyGlobals