it-swarm.com.de

Wie setze und verwende ich globale Variablen? Oder warum man sie überhaupt nicht benutzt

UPDATE: Meine ursprüngliche Frage wurde gelöst, aber dies wird zu einer gültigen Diskussion darüber, warum man keine globalen Variablen verwendet. Ich aktualisiere 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 es jetzt genau das zu tun, was ich wollte. Aber ich benutze immer noch globale Möglichkeiten 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 Thema verwendet werden sollen. 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, das ich sein werde Freigabe für die Verwendung durch andere, sondern ist für einen ganz bestimmten Zweck gebaut.

So erstelle ich sie gerade (ich habe nur einige Variablen eingefügt).

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 tun, die gehen und den gesamten Link für den Code zurückbekommen. Wenn sich das ändert, muss ich es nur an einer Stelle ändern. Ich bin offen für Alternativen, die nicht den globalen Geltungsbereich betreffen.

27
JPollock

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

Wenn Sie versuchen, ein globales Schlüsselwort zu verwenden, müssen Sie zuerst das globale Schlüsselwort angeben. Sie haben es hier bei der Definition seines Werts angegeben, aber außerhalb dieses Bereichs muss es erneut als globale Bereichsvariable deklariert werden.

z.B. in functions.php:

function test() {
    global $hello;
    $hello = 'hello world';
}
add_action( 'after_theme_setup', 'test' );

In single.php funktioniert das nicht:

echo $hello;

Weil $ hello undefiniert ist. Dies aber wird funktionieren:

global $hello;
echo $hello;

Natürlich solltest du beides nicht tun. WordPress versucht bereits, diese Dinge im Objekt-Cache zwischenzuspeichern. Sie werden dabei keine Geschwindigkeitssteigerung bemerken (es kann sein, dass die Geschwindigkeit geringfügig abnimmt). Sie werden lediglich zusätzliche Komplexität und die Notwendigkeit erhalten, viele globale Deklarationen einzugeben, die nicht erforderlich sind.

Sie sollten strukturierte Daten wie Objekte oder Abhängigkeitsinjektionen oder in Ihrem Fall eine Reihe von Funktionen verwenden.

Zum Beispiel ist hier ein Mittel, um etwas Ähnliches über statische Variablen zu tun (immer noch schlecht aus den gleichen Gründen, aber nur ein kleines bisschen weniger und einfacher zu tippen), z.

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

Wenn Sie wirklich Zeit sparen möchten, indem Sie Daten an einem Ort speichern, den Sie wiederverwenden möchten, sollten Sie das WP_Cache-System mit wp_cache_get usw. Verwenden

21
Tom J Nowell

Verwenden Sie keine globalen Variablen , so einfach ist das.

Warum nicht Globals verwenden

Weil der Einsatz von Globals die langfristige Pflege der Software erschwert.

  • Ein Global kann irgendwo im Code deklariert werden, oder nirgendwo, daher gibt es keinen Ort, an dem Sie instinktiv nachsehen können, um einen Kommentar darüber zu finden, wofür das Global verwendet wird
  • Wenn Sie Code lesen, gehen Sie normalerweise davon aus, dass Variablen für die Funktion lokal sind, und verstehen nicht, dass die Änderung ihres Werts in einer Funktion eine systemweite Änderung haben kann.
  • Wenn sie keine Eingabe verarbeiten, sollten Funktionen denselben Wert/dieselbe Ausgabe zurückgeben, wenn sie mit denselben Parametern aufgerufen werden. Durch die Verwendung von Globalen in einer Funktion werden zusätzliche Parameter eingeführt, die in der Funktionsdeklaration nicht dokumentiert sind.
  • globals haben kein spezielles Initialisierungskonstrukt. Daher können Sie nie sicher sein, wann Sie auf den Wert des Globals zugreifen können, und Sie erhalten keine Fehlermeldung, wenn Sie versuchen, vor der Initialisierung auf das Globale zuzugreifen.
  • Jemand anderes (vielleicht ein Plugin) könnte Globals mit demselben Namen verwenden, wodurch Ihr Code ruiniert wird, oder Sie ruinieren ihn, abhängig von der Initialisierungsreihenfolge.

Der WordPress-Kern verwendet viel zu viel Globales. 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. Sie müssen die gesamten Kerndateien durchsuchen, um zu verstehen, wann sie auf true gesetzt ist.

Was kann also getan werden, wenn versucht wird, das Kopieren und Einfügen mehrerer Codezeilen zu beenden, anstatt das Ergebnis der ersten Ausführung in einem globalen Code zu speichern? Es gibt verschiedene Ansätze, funktionale und OOP.

Die Süßstofffunktion. Es ist einfach ein Wrapper/Makro zum Speichern des Copy/Paste

// 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 zu den Aufgaben des früheren globalen Systems gibt und Sie einen offensichtlichen Punkt für das Debuggen haben, wenn der zurückgegebene Wert nicht der erwartete Wert ist.

Sobald Sie einen Süßstoff haben, können Sie das Ergebnis bei Bedarf einfach zwischenspeichern (tun Sie dies nur, wenn Sie feststellen, dass die Ausführung dieser Funktion lange dauert).

function notaglobal($id) {
  static $cache;

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

Auf diese Weise haben Sie dasselbe Verhalten wie bei einem globalen Server, haben jedoch den Vorteil, dass Sie bei jedem Zugriff eine sichere Initialisierung haben.

Sie können ähnliche Muster mit OOP haben. Ich finde, dass OOP in Plugins und Themes normalerweise keinen Wert 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 umständlicher Code, aber wenn Sie mehrere Werte haben, die Sie vorberechnen möchten, weil sie immer verwendet werden, kann dies ein langer Weg sein. Grundsätzlich ist dies ein Objekt, das alle Ihre globalen Elemente auf organisierte Weise enthält. Um zu vermeiden, dass eine Instanz dieses Objekts zu einer globalen Instanz wird (Sie möchten nur eine Instanz, andernfalls berechnen Sie die Werte neu), möchten Sie möglicherweise ein Singleton-Muster verwenden (einige Leute behaupten, es sei eine schlechte Idee, YMMV).

Ich greife nicht gerne direkt auf ein Objektattribut zu, daher verzerrt es in meinem Code weiter

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);
19
Mark Kaplun

Ihre Frage beschäftigt sich mit der Funktionsweise von PHP.

Nehmen Sie als Beispiel $ wpdb

$ wpdb ist eine bekannte globale Variable.

Wissen Sie, wann es deklariert und mit Werten belegt wird?

Jede Seite geladen , yep, jedes Mal, wenn Sie Ihre WordPress-Site besuchen.

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

Obwohl ich kein Theme Designer bin, kann ich sagen, dass after_setup_theme ein einmaliger Hook ist. Es wird nur ausgelöst, wenn das Thema aktiviert ist.

Wenn ich du wäre, würde ich Init oder andere Haken 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 sich also ein Buch aussuchen, wenn Sie sich mit PHP befassen möchten.

6
Jesse

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

<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
2
jgraup