UPDATE: Az eredeti kérdésem megoldódott, de ez érvényes vitává válik arról, hogy miért ne használhatnánk globális változókat, ezért frissítem a kérdést, hogy ezt tükrözze. A megoldás <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
volt, ahogy @TomJNowell javasolta.
2. UPDATE: Most pontosan azt csinálom, amit szerettem volna. De még mindig globális hatókört használok, és örülnék, ha találnék egy jobb módot.
Megpróbálok egy csomó globális változót felállítani a kategóriák állandó hivatkozásaihoz, amelyeket a Saját téma. Ennek legfőbb oka mind a fő navigációban, mind az al navigációk sorozatában való használat, amelyet az aktuális bejegyzés kategóriájának alapján választanak meg. Ez nem téma Majd kiadom mások számára, de egy nagyon meghatározott célra készülök.
Így készítem őket jelenleg (csak néhány változóba illesztettem be).
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" );
Most már megtehetek <?php global $prop; echo $prop; ?>
négy helyet, és visszakapom a kód teljes hivatkozását. Amikor ez megváltozik, csak egy helyen kell megváltoztatnom. Nyitott vagyok azokra az alternatívákra, amelyek nem vonják magukba a globális hatókört.
Megjegyzések
- Melyik linket visszhangozza ez az utasítás az esc_url ($ category_link_prop); megjelenik ? Mi a várható link?
- Miért nem csak a ‘ get_cat_ID (****) ‘ ahol valaha is tervezte a globális változó használatát. Kétlem, hogy lenne bármilyen sebességelőnye annak, ahogyan ezt csinálja. Olvashatóság szempontjából ‘ get_cat_ID (****) ‘ kezet nyer.
- Tudsz újrafogalmazni? Elolvastam a kérdésed, és ‘ még mindig nem vagyok biztos benne, mit és miért akarod csinálni. Általános tanácsom az lenne, hogy ne használj globális változókat, és ne szennyezd a globális hatókört
- ez kicsit úgy hangzik, mint egy X / Y probléma . talán készítsen biztonsági másolatot és magyarázza el, hogy pontosan mi a kívánt eredmény. I ‘ bizonyos itt ‘ sokkal elegánsabb megoldás, mint beállítani egy csomó globális változatot, hogy csak hardkódos hivatkozásokat tegyenek rájuk egy navigációs rendszer másutt
- hozzon létre egy olyan funkciót, amely kiadja a menüt az átadott kontextus alapján így az összes menylogikát és a hozzá tartozó változókat egy helyen tarthatja.
Válasz
Bár erősen tanácsolom ezt, és ez nem nem fogja felgyorsítani a dolgot, a használata helytelen.
A WordPress már gyorsítótárban tárolja ezeket a dolgokat az objektum gyorsítótárában, nem kell az eredményt tárolnia és újrafelhasználnia, a WP ezt már megtette .
Valószínűleg a mikro-optimalizálás eredményeként a kód lassabban fut, nem pedig gyorsabban!
Hogyan használjuk a Globálokat
Amikor globális megoldást próbál használni, először meg kell adnia a global
kulcsszót. Itt adta meg, amikor meghatározza az értékét, de ezen a körön kívül át kell adni, mint globális hatókörű változót.
pl. itt: functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
A single.php
fájlban ez nem fog működni:
echo $hello;
Mivel a $hello
nincs meghatározva. Ez azonban működni fog:
global $hello; echo $hello;
Természetesen egyiket sem szabad tennie. A WordPress már megpróbálja ezeket a dolgokat tárolni az objektum gyorsítótárában .
A globális változók hátrányai és veszélyei
Ezzel nem lesz sebességnövekedés (apró sebességcsökkenést tapasztalhat), csupán további bonyolultságot kap, és sok globális deklaráció beírására van szükség, amelyekre nincs szükség.
Más problémákkal is találkozhat:
- olyan kód, amelyet nem lehet teszteket írni
- olyan kódhoz, amely minden egyes futtatásakor másképp viselkedik
- változó nevekben ütközik egy megosztott névtérből
- véletlen hibák, amikor elfelejtették kijelenteni a
global
- teljes hiányát strukturálja a kódokat az adattároláshoz
- és még sok más
Mit használjon helyette?
Jobb lenne, ha strukturált adatokat, például objektumként vagy függőség-injektálásként, vagy az Ön esetében függvénykészletként.
Statikus változók
Statikus változók nem jó, de gondoljon rájuk, mint a globális változók kissé kevésbé gonosz unokatestvérére.A statikus változók a globális változókhoz tartoznak, mi az iszapos kenyér a cianidhoz.
Például itt van egy eszköz, amellyel hasonlót lehet csinálni statikus változókon keresztül, pl.
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
Szinglettek
A szingulettek olyanok, mint a statikus változók, kivéve, hogy az osztály statikus változót tartalmaz az adott osztály példányával . Ugyanolyan rosszak, mint a globális változók, csak különböző szintaxissal. Kerülje el őket.
WP_Cache, az a dolog, amit megpróbáltál megtenni, de a WP már megtette
Ha nagyon szeretnéd időt takaríthat meg azzal, hogy adatokat tárol valahol az újrafelhasználáshoz, fontolja meg a WP_Cache
rendszer használatát a wp_cache_get
stb. pl.
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Most az értéket a WordPress a kérés teljes élettartama alatt tárolja, megjelenik a hibakereső eszközökben, és ha van egy objektum-gyorsítótárod, akkor a kérelmek között is fennmarad
1. sz. megjegyzés: Megjegyezném, hogy egyesek a globális változókban próbálják megőrizni az adatokat a kérések során, és nincsenek tudatában annak, hogy a PHP nem így működik . A Node alkalmazással ellentétben minden kérelem betölti az alkalmazás egy új példányát, amely a kérelem befejezése után elhal. Ezért az egy kérésre beállított globális változók nem maradnak fenn a következő kérésig.
2. sz. Megjegyzés: A frissített kérdésből kiindulva a globális változók semmilyen teljesítménynövekedést nem jelentenek. Csak akkor kell generálnia a HTML-kódot, amikor és amikor szüksége van rá, és ugyanolyan gyorsan, talán egy kicsit gyorsabban is fut. Ez mikrooptimalizálás.
Megjegyzések
- Tudom, hogy ‘ egy kis dió a globális terjedelemben, de a legtöbb, ha nem az összes változó minden oldalon felhasználásra kerül.
nyitottabb vagyok a jobb ötletekre. Szerkeszteni fogom a kérdést, hogy a szándékomat egy kicsit világosabbá tegyem. A BTW tökéletesen működik, ha a javaslatom szerint<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
tenném. Köszönöm!
Válasz
Ne használja a globális változókat , ilyen egyszerű.
Miért ne globálok használata
Mivel a globálisok használata megnehezíti a szoftver fenntartását hosszú távon.
- Globális deklarálható bárhol a kódban, vagy sehol, ezért nincs olyan hely, ahol ösztönösen megnézhetné, hogy néhány megjegyzést találhasson arról, hogy mire használják a globált.
- A kód olvasása során általában azt feltételezi, hogy A változók lokálisak a függvény szempontjából, és nem értik, hogy egy függvényben az értékük megváltoztatása rendszerszintű változásokat okozhat.
- Ha nem kezelik az inputot, akkor a függvényeknek ugyanazt az értéket / kimenetet kell visszaadniuk, amikor A globálok használata egy függvényben további paramétereket vezet be, amelyek nem szerepelnek a függvény deklarációjában .
- a globálisok nem rendelkeznek konkrét inicializáló konstrukcióval, ezért soha nem lehet biztos abban, hogy mikor férhet hozzá a globális értékéhez, és nem kap hibát, amikor az inicializálás előtt megpróbál hozzáférni a globálishoz .
- Valaki más (esetleg egy plugin) használhatja az azonos nevű globálokat, tönkreteheti a kódot, vagy te tönkreteheti az inicializálási sorrendtől függően.
A WordPress core rendelkezik út a világon sok-sok hasznára. Miközben megpróbálja megérteni, hogyan működnek az olyan alapvető függvények, mint a the_content
, hirtelen rájön, hogy a $more
változó nem lokális, hanem globális, és egészben kell keresnie az alap fájlokból, hogy megértsék, mikor állítják igazra.
Tehát mit lehet tenni, amikor megpróbálja leállítani a másol & több kódsor beillesztését ahelyett, hogy az első futási eredményt globálisan tárolná? Számos megközelítés létezik, funkcionális és OOP.
Az édesítő funkció. Ez egyszerűen egy burkoló / makró a copy / paste mentéshez. van egy nyilvánvaló pontja a hibakereséshez, amikor a visszatérő érték nem az, amire számítasz.
Miután megvan az édesítőszer, könnyen tárolhatja az eredményt, ha szükséges (csak akkor tegye meg, ha rájön, hogy ez a függvény hosszú ideig kell végrehajtani)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Ez ugyanolyan magatartást nyújt egy globális számára, de azzal az előnnyel jár, hogy minden alkalommal, amikor hozzáfér, biztos inicializálást kap.
Az OOP használatával hasonló minták lehetnek. Megállapítottam, hogy az OOP általában nem ad értéket a bővítményekben és a témákban, de ez egy másik vita.
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Ez egy esetlenebb kód, de ha több olyan értékkel rendelkezik, amelyeket előre szeretne kiszámítani, mivel ezeket mindig használják, ez lehet a módja. Alapvetően ez egy olyan objektum, amely szervezetten tartalmazza az összes globálját. Annak elkerülése érdekében, hogy az objektum példánya globális legyen (egy példányt szeretne, különben újra kiszámítja az értékeket) érdemes használni egy szingulett mintát (egyesek szerint rossz ötlet, YMMV) p>
Nem szeretnék közvetlenül hozzáférni egy objektumattribútumhoz, ezért a kódomban még néhányat be fog írni
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);
Megjegyzések
- Kérem, ne ‘ ne kiabáljon . Ne felejtsd el megmagyarázni a miérteket és valamiféle idézetet adni?
- Úgy gondolom, hogy félreértetted a választ. Ha nem ‘ nem próbált volna korai optimalizálást végezni úgy, hogy értékeket tárolt volna a globális változókba, akkor a kód működött volna. A kiabálás azért van, mert a bevett szoftverfejlesztési alapelvek követése ‘ nem eléggé hangsúlyozható. Azoknak az embereknek, akik nem értik ezt az alapelvet (elérhető a helyi Google-n), ne terjesszék a kódot az interneten.
- IMO ez a válasz, azoknak, akik idejönnek a google-ból, látniuk kell, hogy ez rossz ötlet hogy akár azonnal gondolkodjon is a globálok használatáról.
- Ez ‘ nem elég ahhoz, hogy azt mondja: ne csináld az X-et, meg kell magyaráznod, miért vagy úgy nézel ki, mint te id = “348ef6a2e7”>
szeszélyből mondom
Válasz
A kérdésed a php működésével kapcsolatos.
Vegyük példaként a $ wpdb példát
$ wpdb egy jól ismert globális változó.
Tudja, hogy mikor lesz deklarálva és értékekkel rendelve hozzá?
Minden oldal betöltve , igen, minden alkalommal, amikor meglátogatja a wordpress webhelyét.
Hasonlóképpen meg kell győződnie arról, hogy azokat a változókat, amelyeket globalizálni kíván, deklarálják és minden egyes betöltött oldalhoz megfelelő értékeket rendelnek hozzá.
Bár nem vagyok tématervező, elmondhatom, hogy az after_setup_theme az egyik időhorog. csak akkor aktiválódik, amikor a téma aktiválva van.
Ha én lennék, akkor az init vagy más kampókat fogom használni. Nem, ha én lennék, egyáltalán nem fogok globális változókat használni …
Nem igazán tudom megmagyarázni a dolgokat. Tehát vegyen elő egy könyvet, ha elmélyülni akar a PHP-ben.
Válasz
Mindig használhat egy szingulett mintát statikus gettereken keresztül.
<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