UPDATE: Întrebarea mea inițială a fost rezolvată, dar aceasta se transformă într-o discuție validă despre de ce să nu folosim variabile globale, așa că actualizez întrebarea pentru a reflecta asta. Soluția a fost <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
așa cum a sugerat @TomJNowell.
ACTUALIZARE 2: Acum îl fac exact ceea ce îmi doream. Dar încă folosesc domeniul de aplicare global și aș fi fericit să găsesc o modalitate mai bună.
Încerc să stabilesc o grămadă de variabile globale pentru legăturile permanente la categorii care să fie utilizate în diferite locuri din tema. Motivul principal pentru aceasta este pentru utilizarea atât în navigarea principală, cât și într-o serie de sub navigări care sunt alese în funcție de ce categorie este postarea curentă. Aceasta nu este o temă Voi fi lansat pentru utilizare de către alții, dar este construit pentru un scop foarte specific.
Acesta este modul în care le creez în prezent (le-am „lipit doar în câteva dintre variabile).
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" );
Acum pot face <?php global $prop; echo $prop; ?>
în cele 4 locuri care merg și să recuperez întregul link pentru cod. Când se schimbă acest lucru, trebuie să îl schimb doar într-un singur loc. Sunt „deschis la alternativele care nu implică sfera globală.
Comentarii
- Care este legătura care face eco această declarație esc_url ($ category_link_prop); afișează ? Care este linkul dvs. așteptat?
- De ce nu ați folosi doar ‘ get_cat_ID (****) ‘ oriunde ați planificat să utilizați variabila globală. Mă îndoiesc că ar exista vreun avantaj de viteză în modul în care o faceți. Din punct de vedere al lizibilității, ‘ get_cat_ID (****) ‘ câștigă mâinile.
- Poți să reformulezi? Am citit întrebarea ta și ‘ încă nu sunt sigur de ceea ce tu doriți să faceți și de ce doriți să o faceți. Sfatul meu general ar fi să nu utilizați variabile globale și să nu poluați domeniul de aplicare global
- sună un pic ca un Problema X / Y . poate ar trebui să faceți o copie de rezervă și să explicați exact care este rezultatul dorit. Am ‘ m sigur aici ‘ este o soluție mult mai elegantă decât setarea unei grămezi de var-uri globale pentru a face apoi doar referințe hardcode la acestea într-un nav în altă parte
- creați o funcție care vă afișează meniul pe baza contextului pe care îl transmiteți, puteți păstra întreaga logică a meniului și a variabilelor asociate într-un singur loc.
Răspuns
Deși vă sfătuiesc cu tărie împotriva acestui lucru și nu va accelera lucrurile, utilizarea dvs. este incorect.
WordPress deja cache aceste lucruri în cache-ul obiectului, nu este nevoie să stocați rezultatul și să îl refolosiți, WP face asta deja .
Este foarte probabil ca codul dvs. să ruleze mai lent ca urmare a acestei micro-optimizări, nu mai repede!
Cum să utilizați globalii
Când încercați să utilizați o globală, trebuie să specificați mai întâi cuvântul cheie global
. Ați specificat-o aici atunci când îi definiți valoarea, dar în afara acestui domeniu, acesta trebuie redeclarat ca o variabilă de domeniu global.
de ex. în functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
În single.php
, acest lucru nu va funcționa:
echo $hello;
Deoarece $hello
este nedefinit. Totuși, acest lucru va funcționa :
global $hello; echo $hello;
Desigur, nu ar trebui să faceți niciuna. WordPress încearcă deja să cache aceste lucruri în cache-ul obiectului .
Dezavantaje și pericole ale variabilelor globale
Nu veți vedea nicio creștere a vitezei de a face acest lucru (este posibil să vedeți o micșorare a vitezei), tot ce veți obține este o complexitate suplimentară și necesitatea de a tasta o mulțime de declarații globale care nu sunt necesare.
Veți întâlni și alte probleme:
- cod care este imposibil de scris teste pentru
- cod care se comportă diferit de fiecare dată când rulează
- se confruntă cu nume de variabile dintr-un spațiu de nume partajat
- erori accidentale de la uitarea declarării
global
- o lipsă completă de structură pentru stocarea datelor codurilor dvs.
- și multe altele
Ce ar trebui să utilizați în schimb?
Ați fi mai bine să folosiți date structurate, precum ca obiecte sau injecție de dependență sau, în cazul dvs., un set de funcții.
Variabile statice
Variabile statice nu sunt bune, dar gândiți-vă la ele ca la vărul puțin mai malefic al variabilelor globale.Variabilele statice sunt variabile globale, ceea ce înseamnă pâine acoperită cu noroi pentru cianură.
De exemplu, iată un mijloc de a face ceva similar prin intermediul variabilelor statice, de ex.
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
Singletoni
Singletonii sunt ca variabile statice, cu excepția clasei conține o variabilă statică cu o instanță din acea clasă . Sunt „la fel de proaste ca variabilele globale, doar cu o sintaxă diferită. Evitați-le.
WP_Cache, ceea ce ați încercat să faceți, dar WP o face deja
Dacă chiar doriți să economisiți timp stocând date undeva pentru reutilizare, luați în considerare utilizarea sistemului WP_Cache
cu wp_cache_get
etc de ex.
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Acum valoarea va fi stocată în cache pentru durata de viață a cererii de către WordPress, va apărea în instrumentele de depanare și dacă aveți un cache de obiecte, acesta va persista între cereri
Sidenote 1: aș observa că unii oameni încearcă să persiste date în variabile globale între cereri, fără să știe că nu funcționează PHP . Spre deosebire de o aplicație Node, fiecare solicitare încarcă o nouă copie a aplicației, care apoi moare la finalizarea cererii. Din acest motiv, variabilele globale setate la o singură solicitare nu supraviețuiesc la următoarea solicitare
Sidenote 2: Judecând după întrebarea actualizată, variabilele globale nu vă oferă niciun câștig de performanță. Ar trebui să generați codul HTML pe măsură ce aveți nevoie de el și acesta ar rula la fel de repede, poate chiar puțin mai repede. Aceasta este micro-optimizare.
Comentarii
Răspuns
Nu utilizați variabile globale , la fel de simplu.
De ce să nu utilizați globals
Deoarece utilizarea globals face mai dificilă întreținerea software-ului pe termen lung.
- Un program global pot fi declarate oriunde în cod sau nicăieri, de aceea nu există niciun loc în care să puteți privi instinctiv pentru a găsi un comentariu despre ce este utilizat globalul
- În timp ce citiți codul, presupuneți de obicei că variabilele sunt locale pentru funcție și nu înțeleg că schimbarea valorii lor într-o funcție ar putea avea o schimbare la nivel de sistem.
- Dacă nu gestionează intrarea, funcțiile ar trebui să returneze aceeași valoare / ieșire atunci când sunt numiți cu aceiași parametri. Utilizarea globalelor într-o funcție introduce parametri suplimentari care nu sunt documentați în declarația de funcție .
- globalii nu au nicio construcție de inițializare specifică și, prin urmare, nu puteți fi sigur când puteți accesa valoarea globalului și nu primiți nicio eroare când încercați să accesați globalul înainte de inițializare .
- Altcineva (poate un plugin) ar putea folosi globale cu același nume, distrugându-vă codul sau îl distrugeți în funcție de ordinea de inițializare.
Nucleul WordPress are way way way mult spre mult folosirea globals. În timp ce încercați să înțelegeți cum funcționează funcțiile de bază, cum ar fi the_content
, vă dați seama brusc că variabila $more
nu este locală, ci globală și trebuie să caute în întregime din fișierele de bază pentru a înțelege când este setat la adevărat.
Deci, ce se poate face atunci când se încearcă oprirea copierii & de lipire a mai multor linii de cod în loc de stocare a primului rezultat într-o globală? Există mai multe abordări, funcționale și OOP.
Funcția de îndulcitor. Este pur și simplu un wrapper / macro pentru salvarea copierii / lipirii
// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; }
Avantajele sunt că acum există o documentație a ceea ce face fosta globală, iar dvs. aveți un punct evident pentru depanare atunci când valoarea returnată nu este cea pe care o așteptați.
Odată ce aveți un îndulcitor, este ușor să cacheți rezultatul dacă este necesar (faceți-l numai dacă descoperiți că această funcție necesită mult timp de executat)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Acest lucru vă oferă același comportament al unui global, dar cu avantajul de a avea o inițializare asigurată de fiecare dată când îl accesați.
Puteți avea modele similare cu OOP. Am găsit că OOP de obicei nu adaugă nici o valoare în pluginuri și teme, dar aceasta este o discuție diferită
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Acesta este un cod mai neîndemânatic, dar dacă au mai multe valori pe care ați dori să le calculați în prealabil, deoarece acestea sunt întotdeauna utilizate, aceasta poate fi o modalitate de urmat. Practic, acesta este un obiect care conține toate globalele dvs. într-un mod organizat. Pentru a evita ca o instanță a acestui obiect să fie globală (doriți într-o singură instanță, altfel recalculați valorile), poate doriți să utilizați un model singleton (unii oameni susțin că este o idee proastă, YMMV)
Nu-mi place să accesez un atribut obiect direct, așa că în codul meu se va distorsiona mai mult
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);
Comentarii
- Vă rog, nu ‘ nu striga . Îți place să explici de ce și să oferi un fel de citat?
- Cred că ai înțeles greșit răspunsul. Dacă nu ar fi ‘ încercat să facă optimizarea timpurie prin stocarea valorilor în variabile globale, codul său ar fi funcționat. Strigătul se datorează faptului că respectarea principiilor de bază stabilite pentru dezvoltarea software-ului este ceva ce nu poate ‘ să fie suficient de accentuat. Persoanele care nu înțeleg aceste principii de bază (disponibile la google-ul dvs. local) nu ar trebui să răspândească codul pe net.
- IMO acesta este un răspuns, persoanele care vin aici formează google ar trebui să vadă că este o idee proastă să te gândești chiar să folosești globali imediat.
- Nu ‘ nu este suficient să spui că nu faci X, trebuie să explici de ce sau arăți ca tine ‘ o spun din capriciu
- @TomJNowell, mi se pare amuzant că am fost singurul care a votat în jos întrebarea în sine, deoarece era evident în afara domeniului de aplicare al WASE. ‘ nu am văzut valoarea extinderii pe un subiect care nu ar fi trebuit să înceapă deloc aici.
Răspuns
Întrebarea dvs. este legată de modul în care funcționează php.
Luați $ wpdb ca exemplu
$ wpdb este o variabilă globală bine cunoscută.
Știți când va fi declarată și atribuită cu valori?
Fiecare pagină încărcată , da, de fiecare dată când vizitați site-ul dvs. wordpress.
În mod similar, trebuie să vă asigurați că acele variabile pe care doriți să le globalizați vor fi declarate și atribuite cu valorile corespunzătoare la fiecare pagină încărcată.
Deși nu sunt un designer de teme, pot spune că after_setup_theme este una cârlig de timp. va fi declanșat numai când tema este activată.
Dacă aș fi în locul tău, voi folosi init sau alte cârlige. Nu, dacă aș fi în locul tău, nu voi folosi deloc variabile globale …
Nu mă pricep la explicarea lucrurilor. Deci, ar trebui să ridicați o carte dacă doriți să vă adânciți în PHP.
Răspuns
Puteți folosi întotdeauna un model unic prin getters statici.
<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
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
conform sugestiei dvs. Mulțumesc!