UPDATE: Mit oprindelige spørgsmål er løst, men dette bliver til en gyldig diskussion om hvorfor ikke bruge globale variabler, så jeg opdaterer spørgsmålet for at afspejle det. Løsningen blev <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
som @TomJNowell foreslog.
OPDATERING 2: Jeg har det nu til at gøre præcis, hvad jeg ønskede. Men jeg bruger stadig globalt omfang og vil gerne finde en bedre måde.
Jeg forsøger at oprette en hel række globale variabler til permalinks til kategorier, der skal bruges forskellige steder i mit tema. Hovedårsagen til dette er til brug i både hovednavigationen såvel som i en række undernavigationer, der vælges ud fra hvilken kategori det aktuelle indlæg er i. Dette er ikke et tema Jeg frigiver til brug for andre, men er bygget til et meget specifikt formål.
Sådan opretter jeg dem i øjeblikket (jeg har kun indsat nogle få af variablerne).
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 nu gøre <?php global $prop; echo $prop; ?>
på de 4 steder, der går, og få hele linket tilbage til koden. Når det ændrer sig, behøver jeg kun at ændre det ét sted. Jeg er åben for alternativer, der ikke involverer det globale omfang.
Kommentarer
- Hvilket link ekko denne erklæring esc_url ($ category_link_prop); viser ? Hvad er dit forventede link?
- Hvorfor bruger du ikke bare ‘ get_cat_ID (****) ‘ hvor du nogensinde planlagde at bruge den globale variabel. Jeg tvivler på, at der ville være nogen hastighedsfordel, som du gør det. Fra et læsbarheds synspunkt ‘ get_cat_ID (****) ‘ vinder hænderne ned.
- Kan du omformulere? Jeg læste dit spørgsmål, og jeg ‘ er stadig usikker på, hvad du vil gøre, og hvorfor du vil gøre det. Mit generelle råd ville være at ikke bruge globale variabler og ikke at forurene det globale omfang
- dette lyder lidt som en X / Y Problem . måske skal du tage en sikkerhedskopi og forklare nøjagtigt, hvad dit ønskede resultat er. Jeg ‘ er sikker på t her ‘ er en langt mere elegant løsning end at indstille en flok globale vars til så bare hardcode-referencer til dem i en nav andetsteds
- Opret en funktion, der sender din menu baseret på den kontekst, du sender til den, på den måde kan du gemme al menulinik og tilhørende vars indkapslet ét sted.
Svar
Selvom jeg på det kraftigste fraråder dette, og det ikke fremskynder tingene, er din brug forkert.
WordPress gemmer allerede disse ting i objektcachen, du behøver ikke at gemme resultatet og genbruge, WP gør det allerede .
Det er meget sandsynligt, at din kode kører langsommere som et resultat af denne mikrooptimering, ikke hurtigere!
Sådan bruger du globaler
Når du prøver at bruge et globalt, skal du først angive nøgleordet global
. Du har angivet det her, når du definerer dets værdi, men uden for dette omfang skal det omdeklareres som en global omfangsvariabel.
f.eks. i functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
I single.php
fungerer dette ikke:
echo $hello;
Fordi $hello
er udefineret. Dette vil dog fungere:
global $hello; echo $hello;
Du skal selvfølgelig ikke gøre nogen af dem. WordPress forsøger allerede at cache disse ting i objektcachen .
Ulemper og farer ved globale variabler
Du vil ikke se nogen hastighedsforøgelse ved at gøre dette (du kan muligvis se et lille fald i hastighed), alt hvad du får er ekstra kompleksitet og behovet for at skrive mange globale erklæringer, der ikke er nødvendige.
Du vil også støde på andre problemer:
- kode, der er umulig at skrive tests til
- kode, der opfører sig forskelligt hver gang den kører
- sammenstød i variabelnavne fra et delt navneområde
- utilsigtet fejl fra at glemme at erklære
global
- en fuldstændig mangel på struktur til dine koder datalagring
- og mange flere
Hvad skal du bruge i stedet?
Det er bedre for dig at bruge strukturerede data, f.eks. som objekter eller afhængighedsinjektion, eller i dit tilfælde et sæt funktioner.
Statiske variabler
Statiske variabler er ikke gode, men tænk på dem som den lidt mindre onde fætter til globale variabler.Statiske variabler er til globale variabler, hvad mudderdækket brød er for cyanid.
For eksempel er her et middel til at gøre noget 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, bortset fra at klassen indeholder en statisk variabel med en forekomst af den klasse . De er lige så dårlige som globale variabler, bare med forskellig syntaks. Undgå dem.
WP_Cache, den ting du prøvede at gøre, men WP gør det allerede
Hvis du virkelig vil spar tid ved at gemme data et eller andet sted til genbrug, overvej at bruge WP_Cache
-systemet med wp_cache_get
osv. fx
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Nu bliver værdien cachelagret i løbet af WordPress-anmodningen, vises i fejlretningsværktøjer og hvis du har et objekt cache, vil det fortsætte på tværs af anmodninger
Sidenote 1: Jeg vil bemærke, at nogle mennesker forsøger at fastholde data i globale variabler på tværs af anmodninger, uvidende om at det ikke er sådan, PHP fungerer . I modsætning til en node-applikation indlæser hver anmodning en ny kopi af applikationen, som derefter dør, når anmodningen er afsluttet. Af denne grund overlever globale variabler, der er indstillet på en anmodning, ikke til den næste anmodning
Sidenote 2: At dømme ud fra det opdaterede spørgsmål giver dine globale variabler dig slet ingen præstationsgevinst. Du skal bare generere HTML, når du har brug for det, og det kører lige så hurtigt, måske endda en smule hurtigere. Dette er mikrooptimering.
Kommentarer
- Jeg ved det ‘ er lidt nødder til at bruge globalt omfang, men de fleste, hvis ikke alle disse variabler vil blive brugt på hver side. Jeg ‘ er åben for bedre ideer. Jeg vil redigere spørgsmålet for at gøre min hensigt lidt klarere. BTW det fungerer helt fint, når jeg
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
som i dit forslag. Tak! - Ah hvis min løsning fungerer, kan du markere som accepteret? Dine globale variabler er lige så hurtige som at foretage det originale opkald, du vil måske prøve i stedet at bruge funktioner, så du ikke ‘ ikke behøver at skrive 2 linjer, endnu bedre, en singleton, endnu bedre, gør alt det dynamiske og i en skabelondel inkluderet via get_template_part
- Markeret som accepteret som det, hvad jeg laver nu, selvom jeg måske følger en af de strategier, som @MarkKaplun foreslår nedenfor. Brug af get_template_part () er en interessant idé, men jeg ‘ er ikke sikker på, at jeg vil have en dir fuld af korte filer sådan …
- oooh nej nej, du vil ikke ‘ ikke vil have en fil for hver kategori, du ‘ vil bare have den, der griber det aktuelle kategorinavn og bruger det . Du skal ikke ‘ behøver ikke at kode noget, forestil dig besværet med hardcoding det hele
- Jeg sætter koden i mine børnefunktioner.php, som er aktiv. Men jeg kan ikke få adgang til variablen i en php-include-fil, jeg kalder fra en ” normal ” database-genereret post. Rådgiv mig, hvad gør jeg forkert? (Jeg definerer det selvfølgelig som globalt.)
Svar
Brug ikke globale variabler , så simpelt som det.
Hvorfor ikke brug globaler
Fordi brugen af globaler gør det sværere at vedligeholde softwaren på lang sigt.
- En global kan erklæres hvor som helst i koden eller overhovedet ikke, derfor er der intet sted, hvor du instinktivt kan se på for at finde nogle kommentarer om, hvad det globale bruges til
- Mens du læser kode, antager du normalt, at variabler er lokale for funktionen og forstår ikke, at ændring af deres værdi i en funktion kan have en systemændring.
- Hvis de ikke håndterer input, skal funktioner returnere den samme værdi / output, når de kaldes med de samme parametre. Brug af globaler i en funktion introducerer yderligere parametre, som ikke er dokumenteret i funktionserklæringen .
- globaler har ikke nogen specifik initialiseringskonstruktion, og derfor kan du aldrig være sikker på, hvornår du kan få adgang til værdien af det globale, og du får ikke nogen fejl, når du prøver at få adgang til det globale før initialisering .
- En anden (måske et plugin) bruger muligvis globaler med samme navn, ødelægger din kode, eller ødelægger den afhængigt af initialiseringsrækkefølgen.
WordPress-kernen har måde langt meget til meget brug af globaler. Mens du prøver at forstå, hvordan grundlæggende funktioner som the_content
fungerer, indser du pludselig, at $more
-variablen ikke er lokal, men global og skal søges i hele af kernefilerne for at forstå, hvornår er det indstillet til sandt.
Så hvad kan man gøre, når man prøver at stoppe kopiering & at indsætte flere linjer med kode i stedet for at gemme det første kørselsresultat i et globalt? Der er flere tilgange, funktionelle og OOP.
Sødningsfunktionen. Det er simpelthen en indpakning / makro til at gemme kopi / indsæt
// 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 der nu er en dokumentation for, hvad den tidligere globale gør, og du har et indlysende punkt til fejlfinding, når den værdi, der returneres, ikke er den, du forventer.
Når du har et sødemiddel, er det let at cache resultatet, hvis det er nødvendigt (gør det kun, hvis du opdager, at denne funktion tager lang tid at udføre)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Dette giver dig den samme opførsel af en global, men med den fordel, at du har en sikker initialisering, hver gang du får adgang til den.
Du kan have lignende mønstre med OOP. Jeg finder ud af, at OOP normalt ikke tilføjer nogen værdi i plugins og temaer, men dette er en anden diskussion
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Dette er en klodset kode, men hvis du har flere værdier, som du gerne vil beregne på forhånd, fordi de altid bruges, dette kan være en vej at gå. Dybest set er dette et objekt, der indeholder alle dine globaler på en organiseret måde. For at undgå at gøre en forekomst af dette objekt til et globalt (du vil have en forekomst ellers beregner du værdierne). Du kan muligvis bruge et singleton-mønster (nogle mennesker hævder, at det er en dårlig idé, YMMV)
Jeg kan ikke lide at få adgang til en objektattribut direkte, så i min kode vil det vride nogle 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
- Venligst don ‘ t råb . Har du tænkt dig at forklare hvorfor og give en form for citat?
- Jeg tror, du misforstod svaret. Hvis han ikke ‘ ikke forsøgte at foretage en tidlig optimering ved at gemme værdier i globale variabler, ville hans kode have fungeret. Råbet skyldes, at det at følge grundlæggende etablerede softwareudviklingsprincipper er noget, der ‘ ikke kan understreges nok. Folk, der ikke forstår disse grundlæggende principper (findes på din lokale google), bør ikke sprede koden over nettet.
- IMO Dette er et svar, folk, der kommer her fra google, bør se, at det er en dårlig idé at overveje at bruge globaler med det samme.
- Det ‘ er ikke nok til at sige ikke gør X, du skal forklare hvorfor, eller du ligner dig ‘ når jeg siger det på et indfald
- @TomJNowell, finder jeg det sjovt, at jeg var den eneste, der nedstemte selve spørgsmålet, da det naturligvis var uden for rammerne af VASSE. Jeg så ‘ ikke værdien af at udvide til et emne, der overhovedet ikke burde have været startet her.
Svar
Dit spørgsmål er involveret i, hvordan php fungerer.
Tag $ wpdb som eksempel
$ wpdb er en velkendt global variabel.
Ved du, hvornår den bliver erklæret og tildelt værdier?
Hver side indlæst , ja, hver gang du besøger dit wordpress-websted.
På samme måde skal du sørge for, at de variabler, som du vil blive globaliseret, bliver deklareret og tildelt de tilsvarende værdier, hver side indlæses. tidskrog. det “udløses kun, når temaet er aktiveret.
Hvis jeg var dig, bruger jeg init eller andre kroge. Nej, hvis jeg var dig, ville jeg slet ikke bruge globale variabler …
Jeg er virkelig ikke god til at forklare ting. Så du skal hente en bog, hvis du vil dykke ned i PHP.
Svar
Du kan altid bruge et enkelt 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