OPPDATERING: Mitt originale spørsmål er løst, men dette blir en gyldig diskusjon om hvorfor ikke bruke globale variabler, så jeg oppdaterer spørsmålet for å gjenspeile det. Løsningen ble <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
som @TomJNowell foreslo.
OPPDATERING 2: Jeg har det nå til å gjøre akkurat det jeg ønsket. Men jeg bruker fortsatt globalt omfang og vil gjerne finne en bedre måte.
Jeg prøver å sette opp en hel haug med globale variabler for permalinks til kategorier som skal brukes på forskjellige steder i tema. Hovedårsaken til dette er til bruk i både hovednavigasjonen, samt i en serie undernavigasjoner som velges ut fra hvilken kategori det nåværende innlegget er i. Dette er ikke et tema. Jeg vil slippe for bruk av andre, men er bygget for et veldig spesifikt formål.
Slik lager jeg dem for øyeblikket (jeg har bare limt inn noen få av variablene).
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" );
Jeg kan nå gjøre <?php global $prop; echo $prop; ?>
på de 4 stedene som går og få tilbake hele lenken for koden. Når det endres, trenger jeg bare å endre det på ett sted. Jeg er åpen for alternativer som ikke involverer det globale omfanget.
Kommentarer
- Hvilken lenke ekko denne uttalelsen esc_url ($ category_link_prop); viser ? Hva er den forventede lenken din?
- Hvorfor vil du ikke bare bruke ‘ get_cat_ID (****) ‘ uansett hvor du planla å bruke den globale variabelen. Jeg tviler på at det ville være noen hastighetsfordel slik du gjør det. Fra et lesbarhetsperspektiv, ‘ get_cat_ID (****) ‘ vinner hendene ned.
- Kan du omformulere? Jeg leste spørsmålet ditt og jeg ‘ er fortsatt usikker på hva du ønsker å gjøre og hvorfor du vil gjøre det. Mitt generelle råd vil være å ikke bruke globale variabler, og ikke å forurense det globale omfanget
- dette høres litt ut som en X / Y Problem . kanskje du bør sikkerhetskopiere og forklare nøyaktig hva du har ønsket resultat. Jeg ‘ er sikker på her ‘ er en langt mer elegant løsning enn å sette en haug med globale varsler for så bare hardcodereferanser til dem i en nav andre steder
- lag en funksjon som gir ut menyen din basert på konteksten du sender til den, på den måten kan du beholde all menylogikken og tilhørende vars innkapslet på ett sted.
Svar
Selv om jeg fraråder dette, og det vil ikke øke hastigheten, er bruken din feil.
WordPress cacher allerede disse tingene i objektbufferen, du trenger ikke å lagre resultatet og bruke det på nytt, WP gjør det allerede .
Det er sannsynlig at koden din kjører langsommere som et resultat av denne mikrooptimaliseringen, ikke raskere!
Slik bruker du globaler
Når du prøver å bruke et globalt, må du først angi global
nøkkelordet. Du har spesifisert det her når du definerer verdien, men utenfor dette omfanget må den deklareres som en global variabel.
f.eks. i functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
I single.php
, vil dette ikke fungere:
echo $hello;
Fordi $hello
er udefinert. Dette vil imidlertid fungere:
global $hello; echo $hello;
Selvfølgelig bør du ikke gjøre noe av det. WordPress prøver allerede å cache disse tingene i objektbufferen .
Ulemper og farer ved globale variabler
Du vil ikke se noen hastighetsøkning fra å gjøre dette (du kan se en liten hastighetsreduksjon), alt du får er ekstra kompleksitet og behovet for å skrive ut mange globale erklæringer som ikke er nødvendige.
Du vil også støte på andre problemer:
- kode som er umulig å skrive tester for
- kode som oppfører seg annerledes hver gang den kjører
- sammenstøt i variabelnavn fra et delt navneområde
- utilsiktet feil fra å glemme å erklære
global
- en fullstendig mangel på struktur til kodene dine datalagring
- og mange flere
Hva bør du bruke i stedet?
Det er bedre å bruke strukturerte data, for eksempel som objekter eller avhengighetsinjeksjon, eller i ditt tilfelle et sett med funksjoner.
Statiske variabler
Statiske variabler er ikke bra, men tenk på dem som den litt mindre onde fetteren til globale variabler.Statiske variabler er til globale variabler, hva gjørmet dekket brød er for cyanid.
Her er for eksempel et middel for å gjøre noe lignende via statiske variabler f.eks.
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 er som statiske variabler, bortsett fra at klassen inneholder en statisk variabel med en forekomst av den klassen . De er like dårlige som globale variabler, bare med annen syntaks. Unngå dem.
WP_Cache, The Thing You Tried to Do But WP allerede gjør det
Hvis du virkelig vil spar tid ved å lagre data et sted å bruke den igjen, bør du vurdere å bruke WP_Cache
-systemet med wp_cache_get
osv. f.eks.
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Nå blir verdien hurtigbufret for hele forespørselsperioden av WordPress, dukker opp i feilsøkingsverktøy og hvis du har en objektbuffer, vil den fortsette på tvers av forespørsler
Sidenote 1: Jeg vil merke at noen prøver å vedvare data i globale variabler på tvers av forespørsler, uvitende om at dette ikke er hvordan PHP fungerer . I motsetning til et Node-program laster hver forespørsel en ny kopi av applikasjonen, som deretter dør når forespørselen er fullført. Av denne grunn overlever ikke globale variabler som er angitt på en forespørsel til neste forespørsel
Sidenote 2: Bedømt ut fra det oppdaterte spørsmålet, gir dine globale variabler deg ingen ytelsesgevinst i det hele tatt. Du bør bare generere HTML når og når du trenger det, og det vil kjøre like raskt, kanskje til og med litt raskere. Dette er mikrooptimalisering.
Kommentarer
- Jeg vet det ‘ er litt nøtter å bruke globalt omfang, men de fleste, hvis ikke alle disse variablene vil bli brukt på hver side. Jeg ‘ er åpen for bedre ideer. Jeg skal redigere spørsmålet for å gjøre intensjonen min litt tydeligere. BTW det fungerer helt greit når jeg gjør
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
i henhold til ditt forslag. Takk! - Ah, hvis løsningen min fungerer, kan du markere som akseptert? Dine globale variabler er like raske som å ringe det opprinnelige anropet. Det kan være lurt å prøve å bruke funksjoner, så du trenger ikke ‘ ikke å skrive ut to linjer, enda bedre, en singleton, enda bedre, gjør alt det dynamiske og i en maldel inkludert via get_template_part
- Merket som akseptert som det jeg gjør nå, selv om jeg kan gå med en av strategiene som @MarkKaplun foreslår nedenfor. Å bruke get_template_part () er en interessant idé, men jeg ‘ er ikke sikker på at jeg vil ha en dir full av korte filer som det …
- oooh nei nei, du vil ikke ‘ t vil ha en fil for hver kategori, du ‘ vil bare ha den som tar tak i det nåværende kategorienavnet og bruker det . Du bør ikke ‘ ikke trenger å kode noe, forestill deg bryet med å hardkode det hele
- Jeg setter koden i mine barnefunksjoner.php som er aktiv. Men jeg har ikke tilgang til variabelen i en php-include-fil jeg kaller fra en » normal » databasegenerert innlegg. Vennligst gi meg beskjed, hva gjør jeg galt? (Jeg definerer det selvfølgelig som globalt.)
Svar
Ikke bruk globale variabler , så enkelt som det.
Hvorfor ikke bruk globaler
Fordi bruken av globaler gjør det vanskeligere å vedlikeholde programvaren på lang sikt.
- En global kan erklæres hvor som helst i koden, eller ingen steder i det hele tatt, derfor er det ikke noe sted du instinktivt kan se på for å finne noen kommentarer om hva det globale brukes til
- Mens du leser kode, antar du vanligvis at variabler er lokale for funksjonen og forstår ikke at endring av verdien i en funksjon kan ha en systemendring.
- Hvis de ikke håndterer inngang, bør funksjoner returnere samme verdi / utgang når de kalles med samme parametere. Bruk av globaler i en funksjon introduserer tilleggsparametere som ikke er dokumentert i funksjonserklæringen .
- globaler har ikke noen spesifikk initialiseringskonstruksjon, og du kan derfor aldri være sikker på når du får tilgang til verdien til det globale, og du får ikke noen feil når du prøver å få tilgang til det globale før initialisering. .
- Noen andre (et plugin kanskje) kan bruke globaler med samme navn, ødelegge koden din, eller ødelegge den avhengig av initialiseringsrekkefølgen.
WordPress-kjernen har måte mye for mye bruk av globaler. Mens du prøver å forstå hvordan grunnleggende funksjoner som the_content
fungerer, innser du plutselig at $more
-variabelen ikke er lokal, men global og trenger å søke i hele av kjernefilene for å forstå når er det satt til sant.
Så hva kan gjøres når du prøver å stoppe kopiering & å lime inn flere linjer med kode i stedet for å lagre det første kjøringsresultatet i et globalt? Det er flere tilnærminger, funksjonell og OOP.
Søtningsfunksjonen. Det er rett og slett en innpakning / makro for lagring av kopier / lim inn
// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; }
Fordelene er at det nå er en dokumentasjon på hva den tidligere globale gjør, og du har et åpenbart poeng for feilsøking når verdien som returneres ikke er den du forventer.
Når du har fått et søtningsmiddel, er det enkelt å cache resultatet om nødvendig (gjør det bare hvis du oppdager at denne funksjonen tar lang tid å utføre)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Dette gir deg den samme oppførselen til en global, men med fordelen av å ha en sikker initialisering hver gang du får tilgang til den.
Du kan ha lignende mønstre med OOP. Jeg finner ut at OOP vanligvis ikke tilføyer noen verdi i plugins og temaer, men dette er en annen diskusjon
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Dette er en klossete kode, men hvis du har flere verdier som du vil beregne på forhånd fordi de alltid brukes, dette kan være en vei å gå. I utgangspunktet er dette et objekt som inneholder alle dine globaler på en organisert måte. For å unngå å gjøre en forekomst av dette objektet til et globalt (du vil ha en forekomst ellers beregner du verdiene på nytt) kan det være lurt å bruke et singelmønster (noen hevder at det er en dårlig idé, YMMV)
Jeg liker ikke å få tilgang til et objektattributt direkte, så i koden min vil det vride noen flere
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);
Kommentarer
- Vær så snill, ikke ‘ t rop . Har du tenkt å forklare hvorfor og gi noen slags sitater?
- Jeg tror du misforsto svaret. Hvis han ikke ‘ ikke prøvde å gjøre tidlig optimalisering ved å lagre verdier i globale variabler, ville koden ha fungert. Skriket er fordi å følge grunnleggende etablerte programvareutviklingsprinsipper er noe som ‘ ikke kan vektlegges nok. Folk som ikke forstår disse grunnleggende prinsippene (tilgjengelig på din lokale google), bør ikke spre koden over nettet.
- IMO dette er et svar, folk som kommer hit fra google skal se at det er en dårlig idé å til og med tenke på å bruke globaler med en gang.
- Det ‘ er ikke nok til å si ikke gjør X, du må forklare hvorfor eller du ser ut som deg ‘ Når jeg sier det på et innfall
- @TomJNowell, synes jeg det er morsomt at jeg var den eneste som stemte over selve spørsmålet, da det åpenbart var utenfor omfanget av VASK. Jeg så ikke ‘ verdien av å utvide et emne som ikke burde vært startet her i det hele tatt.
Svar
Spørsmålet ditt er involvert i hvordan php fungerer.
Ta $ wpdb som eksempel
$ wpdb er en velkjent global variabel.
Vet du når den blir erklært og tildelt verdier?
Hver side som er lastet inn , ja, hver gang du besøker ditt WordPress-nettsted.
På samme måte må du sørge for at de variablene du vil bli globalisert, blir deklarert og tilordnet tilsvarende verdier hver side lastes inn.
Selv om jeg ikke er temadesigner, kan jeg si at after_setup_theme er en tidskrok. det «bare utløses når temaet er aktivert.
Hvis jeg var deg, vil jeg bruke init eller andre kroker. Nei, hvis jeg var deg, ville jeg ikke bruke globale variabler i det hele tatt …
Jeg er virkelig ikke flink til å forklare ting. Så du bør hente en bok hvis du vil fordype deg i PHP.
Svar
Du kan alltid bruke et singleton-mønster via statiske getters.
<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