AGGIORNAMENTO: La mia domanda originale è stata risolta, ma questa si sta trasformando in una discussione valida sul perché non utilizzare le variabili globali, quindi aggiorno la domanda per riflettere questo. La soluzione era <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
come suggerito da @TomJNowell.
AGGIORNAMENTO 2: Ora faccio esattamente quello che volevo. Ma sto ancora utilizzando lambito globale e sarei felice di trovare un modo migliore.
Sto cercando di impostare un intero gruppo di variabili globali per i permalink alle categorie da utilizzare in vari punti del mio tema. Il motivo principale di ciò è da utilizzare sia nella navigazione principale, sia in una serie di sub navigazioni che vengono scelte in base alla categoria in cui si trova il post corrente. Questo non è un tema Li rilascerò per luso da parte di altri, ma è stato creato per uno scopo molto specifico.
Questo è il modo in cui li creo attualmente (ho incollato solo alcune delle variabili).
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" );
Ora posso fare <?php global $prop; echo $prop; ?>
nei 4 posti che va e recuperare lintero link per il codice. Quando questo cambia, devo solo cambiarlo in un posto. Sono aperto ad alternative che non coinvolgono lambito globale.
Commenti
- Quale collegamento fa questa dichiarazione echo esc_url ($ category_link_prop); ? Qual è il tuo link previsto?
- Perché non dovresti semplicemente utilizzare ‘ get_cat_ID (****) ‘ ovunque tu abbia pianificato di utilizzare la variabile globale. Dubito che ci sarebbe un vantaggio in termini di velocità nel modo in cui lo fai. Dal punto di vista della leggibilità, ‘ get_cat_ID (****) ‘ vince a mani basse.
- Puoi riformulare? Ho letto la tua domanda e ‘ non sono ancora sicuro di ciò che vuoi fare e perché vuoi farlo. Il mio consiglio generale sarebbe di non usare variabili globali e di non inquinare lambito globale
- questo suona un po come un Problema X / Y . forse dovresti eseguire il backup e spiegare esattamente qual è il risultato desiderato. ‘ sono certo qui ‘ è una soluzione molto più elegante rispetto allimpostazione di un gruppo di variabili globali per poi solo codificare i riferimenti ad esse in un menu di navigazione altrove
- crea una funzione che restituisca il tuo menu in base al contesto che gli passi, in questo modo puoi mantenere tutta la logica del menu e le variabili associate incapsulate in un unico posto.
Risposta
Anche se lo sconsiglio vivamente e non velocizza le cose, il tuo utilizzo è non corretto.
WordPress memorizza già queste cose nella cache degli oggetti, non è necessario memorizzare il risultato e riutilizzarlo, WP lo fa già .
È molto probabile che il tuo codice sia più lento a causa di questa microottimizzazione, non più veloce!
Come usare i globali
Quando si tenta di utilizzare un globale, è necessario prima specificare la parola chiave global
. Lhai specificato qui quando ne definisci il valore, ma al di fuori di tale ambito deve essere nuovamente dichiarato come variabile di ambito globale.
ad es. in functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
In single.php
, questo non funzionerà:
echo $hello;
Perché $hello
non è definito. Tuttavia, funzionerà:
global $hello; echo $hello;
Ovviamente non dovresti fare nessuno dei due. WordPress tenta già di memorizzare questi elementi nella cache degli oggetti .
Svantaggi e pericoli delle variabili globali
Non vedrai alcun aumento di velocità facendo questo (potresti vedere una piccola diminuzione della velocità), tutto ciò che otterrai è una complessità aggiuntiva e la necessità di digitare molte dichiarazioni globali che non sono necessarie.
Incontrerai anche altri problemi:
- codice che è impossibile scrivere test per
- codice che si comporta in modo diverso ogni volta che viene eseguito
- conflitti nei nomi delle variabili da uno spazio dei nomi condiviso
- bug accidentali dovuti al dimenticarsi di dichiarare
global
- una completa mancanza di struttura per la memorizzazione dei dati dei tuoi codici
- e molti altri
Cosa dovresti usare invece?
Faresti meglio a usare dati strutturati, come come oggetti o iniezione di dipendenza o, nel tuo caso, un insieme di funzioni.
Variabili statiche
Variabili statiche non sono buoni, ma pensali come cugini leggermente meno cattivi delle variabili globali.Le variabili statiche stanno alle variabili globali, ciò che il pane ricoperto di fango sta al cianuro.
Ad esempio, ecco un modo per fare qualcosa di simile tramite variabili statiche, ad esempio
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
I singleton sono come variabili statiche, tranne per il fatto che la classe contiene una variabile statica con unistanza di quella classe . Sono dannose quanto le variabili globali, solo con una sintassi diversa. Evitali.
WP_Cache, la cosa che hai provato a fare ma WP lo fa già
Se lo vuoi davvero risparmia tempo archiviando i dati da qualche parte per riutilizzarli, valuta lutilizzo del sistema WP_Cache
con wp_cache_get
ecc. ad es.
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Ora il valore verrà memorizzato nella cache per tutta la durata della richiesta da WordPress, verrà visualizzato negli strumenti di debug e se hai una cache degli oggetti, persisterà tra le richieste
Nota a margine 1: Vorrei notare che alcune persone cercano di persistere i dati nelle variabili globali tra le richieste, inconsapevoli che non è così che funziona PHP . A differenza di unapplicazione Node, ogni richiesta carica una nuova copia dellapplicazione, che poi muore quando la richiesta è completata. Per questo motivo le variabili globali impostate su una richiesta non sopravvivono alla richiesta successiva
Nota a margine 2: a giudicare dalla domanda aggiornata, le variabili globali non ti danno alcun guadagno di prestazioni. Dovresti semplicemente generare lHTML come e quando ne hai bisogno e funzionerebbe altrettanto velocemente, forse anche un po più velocemente. Questa è microottimizzazione.
Commenti
- Lo so ‘ è un pazzo usare il ambito globale, ma la maggior parte, se non tutte, queste variabili verranno utilizzate in ogni pagina. ‘ sono aperto a idee migliori. Modificherò la domanda per rendere il mio intento un po più chiaro. A proposito, funziona perfettamente quando eseguo
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
secondo il tuo suggerimento. Grazie! - Ah, se la mia soluzione funziona, potresti contrassegnarla come accettata? Le tue variabili globali sono veloci quanto la chiamata originale, potresti provare invece a usare le funzioni in modo da non ‘ bisogno di digitare 2 righe, meglio ancora, un singleton, meglio ancora, rendi tutto ciò dinamico e in una parte del modello inclusa tramite get_template_part
- Contrassegnato come accettato come ciò che sto facendo ora, anche se posso seguire una delle strategie che @MarkKaplun suggerisce di seguito. Usare get_template_part () è unidea interessante, ma ‘ non sono sicuro di voler avere una directory piena di file brevi come quello …
- oooh no no, non vorresti ‘ un file per ogni categoria, ‘ vorresti solo quello che prende il nome della categoria corrente e lo utilizza . Non dovresti ‘ dover codificare nulla, immagina il fastidio di codificarlo tutto
- Ho inserito il codice nel mio child-functions.php che è attivo. Ma non riesco ad accedere alla variabile in un file php-include che chiamo da un ” normal ” post generato dal database. Per favore avvisami, cosa faccio di sbagliato? (Lo definisco come globale, ovviamente.)
Risposta
Non utilizzare variabili globali , così semplice.
Perché non farlo usa le variabili globali
Perché luso delle globali rende più difficile la manutenzione del software a lungo termine.
- Un globale può essere dichiarato ovunque nel codice, o da nessuna parte, quindi non cè posto in cui puoi istintivamente guardare per trovare qualche commento su ciò per cui viene usato il globale
- Durante la lettura del codice di solito presumi che le variabili sono locali alla funzione e non capiscono che la modifica del loro valore in una funzione potrebbe avere un cambiamento a livello di sistema.
- Se non gestiscono linput, le funzioni dovrebbero restituire lo stesso valore / output quando vengono chiamati con gli stessi parametri Luso di globali in una funzione introduce parametri aggiuntivi che non sono documentati nella dichiarazione della funzione .
- le globali non hanno alcun costrutto di inizializzazione specifico e quindi non puoi mai essere sicuro di poter accedere al valore della globale e non ottieni alcun errore quando cerchi di accedere alla globale prima dellinizializzazione .
- Qualcun altro (forse un plugin) potrebbe usare le variabili globali con lo stesso nome, rovinando il tuo codice o tu lo rovini a seconda dellordine di inizializzazione.
Il core di WordPress ha modo molto molto a molto uso delle globali. Mentre cerchi di capire come funzionano funzioni di base come the_content
, ti rendi improvvisamente conto che la variabile $more
non è locale ma globale e devi cercare lintera dei file core per capire quando è impostato su true.
Quindi cosa si può fare quando si tenta di interrompere la copia & incollando diverse righe di codice invece di memorizzare il risultato della prima esecuzione in un globale? Esistono diversi approcci, funzionali e OOP.
La funzione dolcificante. È semplicemente un wrapper / macro per salvare il copia / incolla
// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; }
I vantaggi sono che ora cè una documentazione su ciò che fa il primo globale, e tu hanno un ovvio punto per il debug quando il valore restituito non è quello che ti aspetti.
Una volta che hai un dolcificante è facile mettere in cache il risultato se necessario (fallo solo se scopri che questa funzione accetta molto tempo per lesecuzione)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Questo ti dà lo stesso comportamento di un globale ma con il vantaggio di avere uninizializzazione sicura ogni volta che vi accedi.
Puoi avere modelli simili con OOP. Trovo che lOOP di solito non aggiunge alcun valore a plugin e temi, ma questa è una discussione diversa
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Questo è un codice più goffo, ma se tu avere diversi valori che vorresti precalcolare perché vengono sempre utilizzati, questo può essere un modo per andare. Fondamentalmente questo è un oggetto che contiene tutti i tuoi globali in modo organizzato. Per evitare di rendere unistanza di questo oggetto un globale (vuoi solo unistanza altrimenti ricalcoli i valori) potresti voler usare un pattern singleton (alcune persone sostengono che sia una cattiva idea, YMMV)
Non mi piace accedere direttamente allattributo di un oggetto, quindi nel mio codice si deformerà un po di più
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);
Commenti
- Per favore, don ‘ t gridare . Ti dispiace spiegare perché e fornire una sorta di citazione?
- Penso che tu abbia frainteso la risposta. Se ‘ non stesse cercando di eseguire lottimizzazione iniziale memorizzando i valori nelle variabili globali, il suo codice avrebbe funzionato. Il grido è perché seguire i principi di sviluppo del software stabiliti di base è qualcosa che ‘ non può essere enfatizzato abbastanza. Le persone che non comprendono questi principi di base (disponibili nel tuo google locale) non dovrebbero diffondere codice in rete.
- IMO questa è una risposta, le persone che vengono qui da google dovrebbero vedere che è una cattiva idea anche solo pensare di usare le variabili globali.
- ‘ non è abbastanza per dire non fare X, devi spiegare perché o sembri ‘ lo dico per capriccio
- @TomJNowell, trovo divertente che io sia stato lunico a votare negativamente la domanda stessa, poiché era ovviamente al di fuori dello scopo di WASE. ‘ non ho visto il valore dellespansione su un argomento che non avrebbe dovuto essere iniziato qui.
Risposta
La tua domanda riguarda il funzionamento di php.
Prendi $ wpdb come esempio
$ wpdb è una variabile globale ben nota.
Sai quando verrà dichiarata e assegnata con valori?
Ogni pagina viene caricata , sì, ogni volta che visiti il tuo sito wordpress.
Allo stesso modo, devi assicurarti che le variabili che desideri globalizzare vengano dichiarate e assegnate con valori corrispondenti a ogni pagina caricata.
Anche se non sono un designer di temi, posso dire che after_setup_theme è uno gancio del tempo. verrà attivato solo quando il tema è attivato.
Se fossi in te, userò init o altri hook. No, se fossi in te, non userei affatto le variabili globali …
Non sono davvero bravo a spiegare le cose. Quindi, dovresti prendere un libro se vuoi approfondire PHP.
Answer
Puoi sempre usare un pattern singleton tramite getter 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