Jak nastavit a používat globální proměnné? Nebo proč je nepoužívat vůbec

UPDATE: Moje původní otázka byla vyřešena, ale to se stává platnou diskusí o tom, proč nepoužívat globální proměnné, takže aktualizuji otázku, aby to odrážela. Řešením bylo <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>, jak navrhl @TomJNowell.

AKTUALIZACE 2: Nyní to dělám přesně to, co jsem chtěl. Ale stále používám globální rozsah a rád bych našel lepší způsob.

Pokouším se nastavit celou řadu globálních proměnných pro trvalé odkazy na kategorie, které se budou používat na různých místech v mém téma. Hlavním důvodem je použití jak v hlavní navigaci, tak v řadě dílčích navigací, které jsou vybrány na základě kategorie, ve které je aktuální příspěvek. Toto není téma Budu uvolňovat pro použití ostatními, ale je vytvořen pro jeden velmi konkrétní účel.

Takto je momentálně vytvářím (vložil jsem pouze několik proměnných).

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" ); 

Nyní můžu udělat <?php global $prop; echo $prop; ?> na 4 místech, která vedou, a získat zpět celý odkaz na kód. Když se to změní, stačí to změnit na jednom místě. Jsem otevřen alternativám, které se netýkají globálního rozsahu.

Komentáře

  • Který odkaz toto tvrzení odráží esc_url ($ category_link_prop); zobrazí ? Jaký je váš očekávaný odkaz?
  • Proč byste prostě nepoužili ‚ get_cat_ID (****) ‚ kdekoli jste plánovali použít globální proměnnou. Pochybuji, že by existovala nějaká rychlostní výhoda, jak to děláte. Z hlediska čitelnosti ‚ get_cat_ID (****) ‚ vyhrává ruce dolů.
  • Dokážete přeformulovat? Přečetl jsem si vaši otázku a stále si nejsem jistý, čím jste chcete udělat a proč to chcete udělat. Moje obecná rada by byla nepoužívat globální proměnné a neznečisťovat globální rozsah
  • to zní trochu jako Problém X / Y . možná byste měli zálohovat a přesně vysvětlit, jaký je váš požadovaný výsledek. Jsem ‚ jistý t zde ‚ je mnohem elegantnější řešení, než nastavit spoustu globálních varů, pak pouze odkazy na ně v pevném odkazu v navigaci jinde
  • vytvořit funkci, která vygeneruje vaši nabídku na základě kontextu, který mu předáte, můžete tímto způsobem uchovávat veškerou logiku nabídky a přidružené vary zapouzdřené na jednom místě.

Odpovědět

I když tomu důrazně nedoporučuji, ne věci nezrychlí, vaše využití je nesprávné.

WordPress již tyto věci ukládá do mezipaměti objektů, nemusíte výsledek ukládat a znovu používat, WP to dělá již .

Je velmi pravděpodobné, že váš kód běží v důsledku této mikrooptimalizace pomaleji, ne rychleji!

Jak používat globály

Při pokusu o použití globálu musíte nejdříve určit klíčové slovo global. Zadali jste jej zde při definování jeho hodnoty, ale mimo tento rozsah je třeba jej znovu deklarovat jako proměnnou globálního rozsahu.

např. v functions.php:

  function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );  

V single.php to nebude fungovat:

  echo $hello;  

Protože $hello není definováno. Toto však bude fungovat:

  global $hello; echo $hello;  

Samozřejmě byste neměli dělat nic. WordPress se již pokouší tyto věci ukládat do mezipaměti v mezipaměti objektů .

Nevýhody a nebezpečí globálních proměnných

Z tohoto procesu neuvidíte žádné zvýšení rychlosti (můžete vidět malé snížení rychlosti), vše, co získáte, je další složitost a potřeba vypsat mnoho globálních deklarací, které nejsou nutné.

Setkáte se také s dalšími problémy:

  • kód, který nelze zapsat pro
  • kód, který se při každém spuštění chová jinak
  • střety v názvech proměnných ze sdíleného prostoru jmen
  • náhodné chyby zapomenutí deklarovat global
  • úplný nedostatek Struktura datového úložiště vašich kódů
  • a mnoho dalších

Co byste místo toho měli použít?

Lepší by vám bylo používat strukturovaná data, například jako vkládání objektů nebo závislostí nebo ve vašem případě sada funkcí.

Statické proměnné

Statické proměnné nejsou dobří, ale považujte je za mírně méně zlého bratrance globálních proměnných.Statické proměnné jsou pro globální proměnné, to, co je blátem pokrytý chléb, pro kyanid.

Například zde existuje způsob, jak něco podobného udělat pomocí statických proměnných, např.

  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

Singletons jsou jako statické proměnné, kromě toho, že třída obsahuje statickou proměnnou s instancí dané třídy . Jsou stejně špatné jako globální proměnné, ale s odlišnou syntaxí. Vyhněte se jim.

WP_Cache, věc, kterou jste se pokusili udělat, ale WP to již dělá

Pokud opravdu chcete ušetřit čas uložením dat někde k opětovnému použití, zvažte použití WP_Cache systému s wp_cache_get atd. např.

 $value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }  

Nyní bude hodnota uložena do mezipaměti po dobu životnosti požadavku WordPressem, zobrazí se v ladicích nástrojích a pokud máte objektovou mezipaměť, bude přetrvávat napříč požadavky


Sidenote 1: Všiml bych si, že někteří lidé se snaží přetrvávat data v globálních proměnných napříč požadavky, aniž by věděli, že takto PHP nefunguje . Na rozdíl od aplikace Node každý požadavek načte novou kopii aplikace, která poté po dokončení požadavku zemře. Z tohoto důvodu globální proměnné nastavené na jeden požadavek nepřežijí na další požadavek.

Sidenote 2: Soudě podle aktualizované otázky vám globální proměnné nedávají vůbec žádný výkon. Prostě byste měli vygenerovat HTML podle potřeby a běžel by stejně rychle, možná dokonce o něco rychleji. Toto je mikrooptimalizace.

Komentáře

  • Vím, že ‚ je trochu ořechů používat globální rozsah, ale většina, pokud ne všechny tyto proměnné budou použity na každé stránce. ‚ Otevřu lepší nápady. Chystám se upravit otázku, aby byl můj záměr trochu jasnější. BTW funguje to naprosto v pořádku, když udělám <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> podle vašeho návrhu. Díky!
  • Ach, pokud moje řešení funguje, můžete označit jako přijaté? Vaše globální proměnné jsou stejně rychlé jako původní volání, můžete místo toho zkusit použít funkce, takže nemusíte ‚ vypisovat 2 řádky, ještě lépe, singleton, ještě lépe, udělejte vše z toho dynamického a v části šablony zahrnuté přes get_template_part
  • Označeno jako přijaté jako to, co teď dělám, i když mohu jít s jednou ze strategií @MarkKaplun navrhuje níže. Používání get_template_part () je zajímavý nápad, ale ‚ si nejsem jistý, zda chci mít adresář plný krátkých podobných souborů …
  • oooh no ne, ‚ nechcete soubor pro každou kategorii, ‚ chcete jen ten, který popadne název aktuální kategorie a použije jej . Neměli byste ‚ nemuset nic napevno kódovat, představte si potíže s pevným kódováním všeho
  • Kód jsem vložil do svého aktivního child-functions.php. Ale nemohu získat přístup k proměnné v souboru php-include, který volám z “ normal “ příspěvku vygenerovaného databází. Prosím, poraďte mi, co dělám špatně? (Samozřejmě to definuji jako globální.)

Odpověď

Nepoužívejte globální proměnné tak jednoduché.

Proč ne používat globály

Protože použití globálů z dlouhodobého hlediska ztěžuje údržbu softwaru.

  • Globální lze deklarovat kdekoli v kódu nebo vůbec nikde, proto neexistuje místo, kde byste se mohli instinktivně podívat a najít nějaký komentář o tom, k čemu se globální používá
  • Při čtení kódu obvykle předpokládáte, že proměnné jsou pro funkci lokální a nerozumí tomu, že změna jejich hodnoty ve funkci může mít celosystémovou změnu.
  • Pokud nezpracovávají vstup, měly by funkce vracet stejnou hodnotu / výstup, když jsou volány se stejnými parametry. Použití globálů ve funkci zavádí další parametry, které nejsou v deklaraci funkce dokumentovány .
  • Globals nemají žádný konkrétní inicializační konstrukt, a proto si nikdy nemůžete být jisti, kdy máte přístup k hodnotě globálu, a při pokusu o přístup k globálu před inicializací se vám nezobrazí žádná chyba. .
  • Někdo jiný (možná plugin) může použít globály se stejným názvem, zničit váš kód nebo jej zničit v závislosti na pořadí inicializace.

Jádro WordPressu má způsobem hodně k velkému využití globálů. Když se snažíte pochopit, jak fungují základní funkce jako the_content, najednou si uvědomíte, že proměnná $more není lokální, ale globální a je třeba ji hledat v celém základních souborů, abyste pochopili, kdy je nastavena na hodnotu true.

Co je tedy možné udělat, když se pokusíte zastavit kopírování & vkládání několika řádků kódu namísto uložení výsledku prvního spuštění do globálního? Existuje několik přístupů, funkční a OOP.

Funkce sladidla. Je to prostě obal / makro pro uložení kopírování / vložení.

// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; } 

Výhody spočívají v tom, že nyní existuje dokumentace k tomu, co dělá bývalý globální, a vy mít zřejmý bod pro ladění, když vrácená hodnota není ta, kterou očekáváte.

Jakmile máte sladidlo, můžete v případě potřeby snadno uložit výsledek do mezipaměti (proveďte to, pouze pokud zjistíte, že tato funkce trvá dlouhá doba k provedení)

function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; } 

Tím získáte stejné chování globálního, ale s výhodou, že máte zajištěnou inicializaci při každém přístupu.

S OOP můžete mít podobné vzory. Zjistil jsem, že OOP obvykle nepřidává žádnou hodnotu do pluginů a témat, ale toto je jiná diskuse

class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2; 

Toto je neohrabaný kód, ale pokud mít několik hodnot, které byste chtěli předem vypočítat, protože se vždy používají, může to být způsob, jak jít. V zásadě se jedná o objekt, který obsahuje všechny vaše globály organizovaným způsobem. Chcete-li zabránit tomu, aby se instance tohoto objektu stala globálním (chcete pouze jednu instanci, jinak přepočítáte hodnoty), možná budete chtít použít singletonový vzor (někteří lidé tvrdí, že je to špatný nápad, YMMV)

Nelíbí se mi přímý přístup k atributu objektu, takže v mém kódu to bude warpe více

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); 

Komentáře

  • Prosím, nekřičte ‚ . Chcete vysvětlit proč a uvést nějaký citát?
  • Myslím, že jste špatně pochopili odpověď. Pokud by se ‚ nepokoušel o časnou optimalizaci ukládáním hodnot do globálních proměnných, jeho kód by fungoval. Křičí, protože dodržování základních zavedených principů vývoje softwaru je něco, co ‚ nelze dostatečně zdůraznit. Lidé, kteří nerozumí těmto základním principům (k dispozici na vašem místním google), by neměli šířit kód po síti.
  • Toto je odpověď, lidé, kteří sem přicházejí z google, by měli vidět, že je to špatný nápad dokonce přemýšlet o okamžitém použití globálů.
  • ‚ Nestačí říct, že nedělej X, musíš vysvětlit proč nebo vypadáš jako ‚ říkám to z rozmaru
  • @TomJNowell, připadá mi legrační, že jsem byl jediný, kdo odmítl otázku sám, protože to bylo zjevně mimo rozsah WASE. Neviděl jsem ‚ hodnotu rozšíření na téma, které zde vůbec nemělo být zahájeno.

Odpověď

Vaše otázka souvisí s tím, jak funguje php.

Jako příklad použijte $ wpdb

$ wpdb je známá globální proměnná.

Víte, kdy bude deklarována a přiřazena hodnotami?

Každá stránka načtena , ano, pokaždé, když navštívíte svůj web wordpress.

Podobně musíte zajistit, aby proměnné, které chcete globalizovat, byly deklarovány a přiřazeny s odpovídajícími hodnotami každé načtené stránce.

Ačkoli nejsem návrhář motivů, mohu říci, že after_setup_theme je jedna časový háček. „Spustí se to pouze při aktivaci motivu.

Kdybych byl tebou, použiji init nebo jiné háčky. Ne, na tvém místě nebudu vůbec používat globální proměnné …

Opravdu nedokážu vysvětlit věci. Pokud se chcete ponořit do PHP, měli byste si vyzvednout knihu.

Odpovědět

Vždy můžete použít singletonový vzor prostřednictvím statických getrů.

<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 

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *