Wie setze und verwende ich globale Variablen? Oder warum nicht überhaupt verwenden?

UPDATE: Meine ursprüngliche Frage wurde gelöst, aber dies wird zu einer gültigen Diskussion darüber, warum keine globalen Variablen verwendet werden sollen. Daher aktualisiere ich die Frage, um dies widerzuspiegeln. Die Lösung war <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> wie von @TomJNowell vorgeschlagen.

UPDATE 2: Ich habe jetzt genau das getan, was ich wollte. Aber ich verwende immer noch den globalen Bereich und würde gerne einen besseren Weg finden.

Ich versuche, eine ganze Reihe globaler Variablen für die Permalinks zu Kategorien einzurichten, die an verschiedenen Stellen in meinem verwendet werden sollen Thema. Der Hauptgrund dafür ist die Verwendung sowohl in der Hauptnavigation als auch in einer Reihe von Unternavigationen, die basierend auf der Kategorie ausgewählt werden, in der sich der aktuelle Beitrag befindet. Dies ist kein Thema Ich werde es für andere freigeben, es wurde jedoch für einen ganz bestimmten Zweck erstellt.

So erstelle ich sie derzeit (ich habe nur einige der Variablen eingefügt). P. >

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

Ich kann jetzt <?php global $prop; echo $prop; ?> an den 4 Stellen ausführen und den gesamten Link für den Code zurückerhalten. Wenn sich das ändert, muss ich es nur an einer Stelle ändern. Ich bin offen für Alternativen, die nicht den globalen Bereich betreffen.

Kommentare

  • Welchen Link gibt diese Anweisung wieder? Esc_url ($ category_link_prop); wird angezeigt Was ist Ihr erwarteter Link?
  • Warum sollten Sie nicht einfach ‚ get_cat_ID (****) ‚ Wo immer Sie die globale Variable verwenden wollten. Ich bezweifle, dass es einen Geschwindigkeitsvorteil gibt, wenn Sie dies tun. Unter dem Gesichtspunkt der Lesbarkeit ‚ get_cat_ID (****) ‚ gewinnt zweifellos.
  • Können Sie umformulieren? Ich habe Ihre Frage gelesen und ‚ bin mir immer noch nicht sicher, was Sie sind Ich möchte dies tun und warum Sie es tun möchten. Mein allgemeiner Rat wäre, keine globalen Variablen zu verwenden und den globalen Bereich nicht zu verschmutzen.
  • Dies klingt ein bisschen wie ein X / Y-Problem . Vielleicht sollten Sie ein Backup erstellen und genau erklären, was Ihr gewünschtes Ergebnis ist. Ich ‚ bin mir sicher, t Hier ist ‚ eine weitaus elegantere Lösung als das Festlegen einer Reihe globaler Variablen, um dann nur Verweise auf sie in einem Navi an anderer Stelle fest zu codieren.
  • Erstellen Sie eine Funktion, die Ihr Menü ausgibt Basierend auf dem Kontext, den Sie an ihn übergeben, können Sie auf diese Weise die gesamte Menülogik und die zugehörigen Variablen an einem Ort kapseln.

Antwort

Ich rate zwar dringend davon ab und es wird nicht die Dinge beschleunigen, aber Ihre Verwendung ist falsch.

WordPress speichert diese Dinge bereits im Objektcache, Sie müssen das Ergebnis nicht speichern und wiederverwenden, WP macht das bereits .

Es ist sehr wahrscheinlich, dass Ihr Code aufgrund dieser Mikrooptimierung langsamer und nicht schneller ausgeführt wird!

Verwendung von Globals

Wenn Sie versuchen, ein globales Schlüsselwort zu verwenden, müssen Sie zuerst das Schlüsselwort global angeben. Sie haben es hier angegeben, als Sie seinen Wert definiert haben, aber außerhalb dieses Bereichs muss es als globale Bereichsvariable neu deklariert werden.

z. in functions.php:

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

In single.php funktioniert dies nicht:

  echo $hello;  

Weil $hello undefiniert ist. Dies funktioniert jedoch :

  global $hello; echo $hello;  

Natürlich sollten Sie beides nicht tun. WordPress versucht bereits, diese Dinge im Objektcache zwischenzuspeichern .

Nachteile und Gefahren globaler Variablen

Sie werden dabei keine Geschwindigkeitssteigerung feststellen (möglicherweise eine geringfügige Geschwindigkeitsabnahme). Sie erhalten lediglich zusätzliche Komplexität und die Notwendigkeit, viele globale Deklarationen einzugeben, die nicht erforderlich sind.

Sie werden auch auf andere Probleme stoßen:

  • Code, der keine Tests für
  • Code schreiben kann, der sich bei jeder Ausführung anders verhält
  • kollidiert in Variablennamen aus einem gemeinsam genutzten Namensraum
  • versehentliche Fehler, weil vergessen wurde, global
  • einen vollständigen Mangel an zu deklarieren Strukturierung Ihrer Codes Datenspeicherung
  • und viele mehr

Was sollten Sie stattdessen verwenden?

Sie sollten strukturierte Daten verwenden, z als Objekte oder Abhängigkeitsinjektion oder in Ihrem Fall als Funktionssatz.

Statische Variablen

Statische Variablen sind nicht gut, aber betrachten Sie sie als den etwas weniger bösen Cousin globaler Variablen.Statische Variablen sind globale Variablen, was mit Schlamm bedecktes Brot Cyanid ist.

Hier ist beispielsweise ein Mittel, um etwas Ähnliches über statische Variablen zu tun, z. B.

  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 sind wie statische Variablen, außer dass die Klasse eine statische Variable mit einer Instanz dieser Klasse enthält . Sie sind genauso schlecht wie globale Variablen, nur mit unterschiedlicher Syntax. Vermeiden Sie sie.

WP_Cache, das, was Sie versucht haben, aber WP tut es bereits

Wenn Sie es wirklich wollen Sparen Sie Zeit, indem Sie Daten an einem Ort speichern, der wiederverwendet werden soll. Verwenden Sie das System WP_Cache mit wp_cache_get usw., z. B.

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

Jetzt wird der Wert für die Dauer der Anforderung von WordPress zwischengespeichert, in Debugging-Tools angezeigt und Wenn Sie einen Objektcache haben, bleibt dieser über Anforderungen hinweg bestehen.


Nebenbemerkung 1: Ich möchte darauf hinweisen, dass einige Benutzer versuchen, Daten in globalen Variablen über Anforderungen hinweg beizubehalten, ohne zu wissen, dass PHP nicht so funktioniert . Im Gegensatz zu einer Knotenanwendung lädt jede Anforderung eine neue Kopie der Anwendung, die dann stirbt, wenn die Anforderung abgeschlossen ist. Aus diesem Grund überleben globale Variablen, die für eine Anforderung festgelegt wurden, nicht bis zur nächsten Anforderung.

Nebenbemerkung 2: Gemessen an der aktualisierten Frage bieten Ihre globalen Variablen überhaupt keinen Leistungsgewinn. Sie sollten den HTML-Code einfach nach Bedarf generieren und er würde genauso schnell ausgeführt, vielleicht sogar ein kleines bisschen schneller. Dies ist eine Mikrooptimierung.

Kommentare

  • Ich weiß, dass ‚ eine kleine Nuss ist, um die zu verwenden globaler Bereich, aber die meisten, wenn nicht alle dieser Variablen werden auf jeder Seite verwendet. Ich ‚ bin offen für bessere Ideen. Ich werde die Frage bearbeiten, um meine Absicht ein wenig klarer zu machen. Übrigens funktioniert es einwandfrei, wenn ich <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> gemäß Ihrem Vorschlag mache. Danke!
  • Ah, wenn meine Lösung funktioniert, können Sie sie als akzeptiert markieren? Ihre globalen Variablen sind genauso schnell wie der ursprüngliche Aufruf. Vielleicht möchten Sie stattdessen Funktionen verwenden, damit Sie nicht ‚ 2 Zeilen eingeben müssen, besser noch einen Singleton. Besser noch, machen Sie all das dynamisch und in einem Vorlagenteil, der über get_template_part
  • enthalten ist. Als akzeptiert markiert, was ich jetzt mache, obwohl ich möglicherweise eine der Strategien wählen kann, die @MarkKaplun unten vorschlägt. Die Verwendung von get_template_part () ist eine interessante Idee, aber ich ‚ bin mir nicht sicher, ob ich ein Verzeichnis voller kurzer Dateien wie diese haben möchte …
  • oooh nein Nein, Sie möchten ‚ keine Datei für jede Kategorie, ‚ möchten nur die Datei, die den aktuellen Kategorienamen erfasst und diese verwendet . Sie sollten ‚ nichts fest codieren müssen. Stellen Sie sich den Aufwand vor, alles fest zu codieren.
  • Ich habe den Code in meine untergeordnete function.php eingefügt. Ich kann jedoch nicht auf die Variable in einer PHP-Include-Datei zugreifen, die ich von einem “ normalen “ datenbankgenerierten Beitrag aufrufe. Bitte raten Sie mir, was mache ich falsch? (Ich definiere es natürlich als global.)

Antwort

Verwenden Sie keine globalen Variablen , so einfach ist das.

Warum nicht? Verwenden Sie Globals

Da die Verwendung von Globals die langfristige Wartung der Software erschwert.

  • Ein Global kann irgendwo im Code oder nirgendwo deklariert werden, daher gibt es keinen Ort, an dem Sie instinktiv nachsehen können, um einen Kommentar darüber zu finden, wofür das Globale verwendet wird.
  • Beim Lesen von Code nehmen Sie dies normalerweise an Variablen sind für die Funktion lokal und verstehen nicht, dass sich das Ändern ihres Werts in einer Funktion systemweit ändern kann.
  • Wenn sie keine Eingaben verarbeiten, sollten Funktionen denselben Wert / dieselbe Ausgabe zurückgeben, wenn sie werden mit denselben Parametern aufgerufen. Durch die Verwendung von Globals in einer Funktion werden zusätzliche Parameter eingeführt, die in der Funktionsdeklaration nicht dokumentiert sind .
  • Globale haben kein spezifisches Initialisierungskonstrukt und daher können Sie nie sicher sein, wann Sie auf den Wert der globalen zugreifen können, und Sie erhalten keine Fehler, wenn Sie versuchen, vor der Initialisierung auf die globale zuzugreifen .
  • Jemand anderes (vielleicht ein Plugin) verwendet möglicherweise Globals mit demselben Namen, wodurch Ihr Code ruiniert wird, oder Sie ruinieren ihn je nach Initialisierungsreihenfolge.

WordPress-Kern hat Weg viel viel viel Gebrauch von Globalen. Beim Versuch zu verstehen, wie grundlegende Funktionen wie the_content funktionieren, stellen Sie plötzlich fest, dass die Variable $more nicht lokal, sondern global ist und als Ganzes gesucht werden muss der Kerndateien zu verstehen, wann es auf true gesetzt ist.

Was kann also getan werden, wenn versucht wird, das Kopieren von & das Einfügen mehrerer Codezeilen zu stoppen, anstatt das erste Ausführungsergebnis in einem globalen zu speichern? Es gibt verschiedene Ansätze, funktionale und OOP.

Die Süßstofffunktion. Es ist einfach ein Wrapper / Makro zum Speichern des Kopierens / Einfügens.

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

Die Vorteile sind, dass es jetzt eine Dokumentation darüber gibt, was die frühere globale und Sie tun Ein offensichtlicher Punkt für das Debuggen ist, wenn der zurückgegebene Wert nicht der erwartete ist.

Sobald Sie einen Süßstoff haben, können Sie das Ergebnis bei Bedarf einfach zwischenspeichern (tun Sie dies nur, wenn Sie feststellen, dass diese Funktion erforderlich ist lange Ausführungszeit)

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

Dies gibt Ihnen das gleiche Verhalten eines globalen, jedoch mit dem Vorteil, dass Sie bei jedem Zugriff eine sichere Initialisierung haben.

Mit OOP können Sie ähnliche Muster erstellen. Ich finde, dass OOP normalerweise keinen Wert in Plugins und Themes hinzufügt, aber dies ist eine andere Diskussion.

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

Dies ist ein ungeschickterer Code, aber wenn Sie Wenn Sie mehrere Werte vorberechnen möchten, da diese immer verwendet werden, kann dies ein guter Weg sein. Grundsätzlich ist dies ein Objekt, das alle Ihre Globals auf organisierte Weise enthält. Um zu vermeiden, dass eine Instanz dieses Objekts global wird (Sie möchten nur eine Instanz, andernfalls berechnen Sie die Werte neu.) Möglicherweise möchten Sie ein Singleton-Muster verwenden (einige Leute behaupten, es sei eine schlechte Idee, YMMV)

Ich möchte nicht direkt auf ein Objektattribut zugreifen, daher werden in meinem Code weitere

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

Kommentare

verzogen

  • Bitte, ‚ nicht schreien . Möchten Sie erklären, warum und eine Art Zitat angeben?
  • Ich denke, Sie haben die Antwort falsch verstanden. Wenn er nicht ‚ versucht hätte, eine frühzeitige Optimierung durch Speichern von Werten in globalen Variablen durchzuführen, hätte sein Code funktioniert. Das Geschrei ist, weil das Befolgen grundlegender Prinzipien der Softwareentwicklung etwas ist, das ‚ nicht genug betont werden kann. Personen, die dieses Grundprinzip nicht verstehen (verfügbar bei Ihrem lokalen Google), sollten keinen Code über das Internet verbreiten.
  • IMO Dies ist eine Antwort. Personen, die von Google hierher kommen, sollten sehen, dass dies eine schlechte Idee ist Um überhaupt daran zu denken, sofort Globals zu verwenden.
  • Es ‚ reicht nicht aus, um zu sagen, mach kein X, du musst erklären, warum oder du siehst aus wie du ‚ sage es aus einer Laune heraus
  • @TomJNowell, ich finde es lustig, dass ich der einzige war, der die Frage selbst abgelehnt hat, da sie offensichtlich außerhalb des Rahmens von lag WASE. Ich habe ‚ den Wert der Erweiterung eines Themas nicht gesehen, das hier überhaupt nicht hätte beginnen sollen.

Antwort

Ihre Frage betrifft die Funktionsweise von PHP.

Nehmen Sie $ wpdb als Beispiel

$ wpdb ist eine bekannte globale Variable.

Wissen Sie, wann sie deklariert und mit Werten versehen wird?

Jede geladene Seite , ja, jedes Mal, wenn Sie Ihre WordPress-Site besuchen.

In ähnlicher Weise müssen Sie sicherstellen, dass die Variablen, die globalisiert werden sollen, deklariert und bei jeder geladenen Seite mit entsprechenden Werten zugewiesen werden.

Obwohl ich kein Designdesigner bin, kann ich feststellen, dass das after_setup_theme eine ist Zeithaken. Es wird nur ausgelöst, wenn das Thema aktiviert ist.

Wenn ich Sie wäre, würde ich init oder andere Hooks verwenden. Nein, wenn ich Sie wäre, würde ich überhaupt keine globalen Variablen verwenden …

Ich bin wirklich nicht gut darin, Dinge zu erklären. Sie sollten also ein Buch in die Hand nehmen, wenn Sie sich mit PHP befassen möchten.

Antwort

Sie können immer ein Singleton-Muster verwenden über statische Getter.

<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 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.