webentwicklung-frage-antwort-db.com.de

Werden globale Variablen in PHP als schlechte Praxis angesehen? Wenn ja, warum?

function foo () {
    global $var;
    // rest of code
}

In meinen kleinen PHP) Projekten gehe ich normalerweise den prozeduralen Weg. Ich habe im Allgemeinen eine Variable, die die Systemkonfiguration enthält, und wenn ich in einer Funktion auf diese Variable zugreifen muss, mache ich global $var;.

Ist das schlechte Praxis?

84
KRTac

Wenn in anderen Sprachen über globale Variablen gesprochen wird, hat dies eine andere Bedeutung als in PHP. Das liegt daran, dass Variablen in PHP nicht wirklich global sind. Der Gültigkeitsbereich eines typischen PHP) - Programms ist eine HTTP-Anforderung. Sitzungsvariablen haben tatsächlich einen größeren Gültigkeitsbereich als PHP "globale" Variablen, da sie normalerweise viele HTTP-Anforderungen umfassen .

Oft (immer?) Können Sie Member-Funktionen in Methoden wie preg_replace_callback() wie folgt aufrufen:

preg_replace_callback('!pattern!', array($obj, 'method'), $str);

Siehe Rückrufe für mehr.

Der Punkt ist, dass Objekte auf PHP) geschraubt wurden und in gewisser Weise zu Unbeholfenheit führen.

Kümmern Sie sich nicht zu sehr darum, Standards oder Konstrukte aus verschiedenen Sprachen auf PHP anzuwenden. Eine weitere häufige Gefahr besteht darin, PHP zu einer reinen OOP Sprache zu machen, indem man Objektmodelle über alles klebt.

Verwenden Sie wie alles andere "globale" Variablen, prozeduralen Code, ein bestimmtes Framework und OOP weil es sinnvoll ist, ein Problem löst, die Menge an Code, die Sie schreiben müssen, reduziert oder die Wartbarkeit erhöht und einfacher zu verstehen, nicht weil Sie denken, dass Sie sollten.

98
cletus

Globale Variablen, die nicht sorgfältig verwendet werden, können das Auffinden von Problemen erschweren. Angenommen, Sie fordern ein PHP-Skript an und erhalten eine Warnung, dass Sie versuchen, auf einen Index eines Arrays zuzugreifen, der in einer Funktion nicht vorhanden ist.

Wenn das Array, auf das Sie zugreifen möchten, lokal für die Funktion ist, überprüfen Sie die Funktion, um festzustellen, ob Sie dort einen Fehler gemacht haben. Möglicherweise liegt ein Problem mit einer Eingabe für die Funktion vor. Überprüfen Sie daher die Stellen, an denen die Funktion aufgerufen wird.

Wenn dieses Array jedoch global ist, müssen Sie alle Stellen überprüfen, an denen Sie diese globale Variable verwenden, und nicht nur, dass Sie herausfinden müssen, in welcher Reihenfolge auf diese Verweise auf die globale Variable zugegriffen wird.

Wenn Sie eine globale Variable in einem Codeteil haben, ist es schwierig, die Funktionalität dieses Codes zu isolieren. Warum möchten Sie die Funktionalität isolieren? So können Sie es testen und an anderer Stelle wiederverwenden. Wenn Sie Code haben, den Sie nicht testen und nicht wiederverwenden müssen, ist die Verwendung globaler Variablen in Ordnung.

27
rojoca

ich stimme Cletus zu. Ich würde zwei Dinge hinzufügen:

  1. verwenden Sie ein Präfix, damit Sie es sofort als global identifizieren können (z. B. $ g_).
  2. deklarieren Sie sie an einer Stelle und streuen Sie sie nicht rund um den Code.

viele Grüße, Don

16
Don Dickinson

Wer kann gegen Erfahrung, Hochschulabschlüsse und Software-Engineering argumentieren? Nicht ich. Ich würde nur sagen, dass ich bei der Entwicklung objektorientierter Einzelseitenanwendungen PHP mehr Spaß habe, wenn ich weiß, dass ich das Ganze von Grund auf neu erstellen kann, ohne mir Gedanken über Namespace-Kollisionen zu machen. Bauen von Grund auf ist etwas, was viele Menschen nicht mehr tun. Sie haben einen Job, eine Frist, einen Bonus oder einen guten Ruf. Diese Typen neigen dazu, so viel vorgefertigten Code mit hohem Einsatz zu verwenden, dass sie es gar nicht riskieren können, globale Variablen zu verwenden.

Es mag schlecht sein, globale Variablen zu verwenden, auch wenn sie nur im globalen Bereich eines Programms verwendet werden, aber vergessen wir nicht diejenigen, die nur Spaß haben und etwas zum Laufen bringen wollen.

Wenn das bedeutet, dass einige Variablen (<10) im globalen Namespace verwendet werden, werden diese nur im globalen Bereich eines Programms verwendet. Ja, ja, MVC, Abhängigkeitsinjektion, externer Code, bla, bla, bla, bla. Wenn Sie jedoch 99,99% Ihres Codes in Namespaces und Klassen enthalten und externen Code in einer Sandbox gespeichert haben, wird die Welt nicht enden (ich wiederhole, die Welt wird nicht enden), wenn Sie eine globale Variable verwenden.

Im Allgemeinen würde ich nicht sagen, dass die Verwendung globaler Variablen schlechte Praxis ist. Ich würde sagen, dass die Verwendung globaler Variablen (Flags und dergleichen) außerhalb des globalen Bereichs eines Programms nach Problemen fragen und (auf lange Sicht) schlecht beraten ist, weil Sie können den Überblick über ihre Zustände ziemlich leicht verlieren. Außerdem würde ich sagen, dass je mehr Sie lernen, desto weniger sind Sie abhängig von globalen Variablen, weil Sie die "Freude" erlebt haben, Fehler aufzuspüren, die mit ihrer Verwendung verbunden sind. Dies allein wird Sie dazu anregen, einen anderen Weg zu finden, um dasselbe Problem zu lösen. Zufälligerweise tendiert dies dazu, PHP Personen dazu zu bringen, den Umgang mit Namespaces und Klassen (statische Member usw.) zu erlernen.

Das Gebiet der Informatik ist riesig. Wenn wir alle davon abhalten, etwas zu tun, weil wir es als schlecht bezeichnen, verlieren sie den Spaß daran, die Gründe für das Etikett wirklich zu verstehen.

Verwenden Sie globale Variablen, wenn Sie müssen, aber versuchen Sie dann, das Problem ohne sie zu lösen. Kollisionen, Testen und Debuggen bedeuten mehr, wenn Sie die wahre Natur des Problems genau verstehen und nicht nur eine Beschreibung des Problems.

5

Von der beendeten SO Documentation Beta

Wir können dieses Problem mit dem folgenden Pseudocode veranschaulichen

function foo() {
     global $bob;
     $bob->doSomething();
}

Ihre erste Frage ist offensichtlich

Woher kommt $bob?

Bist du verwirrt? Gut. Sie haben gerade erfahren, warum Globals verwirrend sind und als schlechte Praxis gelten. Wenn dies ein echtes Programm wäre, wäre es Ihr nächster Spaß, alle Instanzen von $bob Aufzuspüren und zu hoffen, dass Sie die richtige finden (dies wird schlimmer, wenn $bob Überall verwendet wird). Schlimmer noch, wenn jemand anderes $bob Definiert (oder Sie diese Variable vergessen und erneut verwendet haben), kann Ihr Code kaputt gehen (im obigen Codebeispiel würde ein falsches Objekt oder gar kein Objekt einen schwerwiegenden Fehler verursachen) ). Da praktisch alle PHP) - Programme Code wie include('file.php'); verwenden, wird die Verwaltung Ihres Codes umso schwieriger, je mehr Dateien Sie hinzufügen.

Wie vermeiden wir Globals?

Der beste Weg, Globales zu vermeiden, ist eine Philosophie namens Dependency Injection. Hier geben wir die benötigten Werkzeuge an die Funktion oder Klasse weiter.

function foo(\Bar $bob) {
    $bob->doSomething();
}

Dies ist viel leichter zu verstehen und zu pflegen. Es lässt sich nicht erraten, wo $bob Eingerichtet wurde, da der Anrufer dafür verantwortlich ist, dies zu wissen (er gibt uns das, was wir wissen müssen). Besser noch, wir können Typdeklarationen verwenden, um die Übergabe einzuschränken. Wir wissen also, dass $bob Entweder eine Instanz der Klasse Bar oder eine Instanz eines untergeordneten Objekts von Bar ist, dh wir wissen, dass wir die Methoden dieser Klasse verwenden können. In Kombination mit einem Standard-Autoloader (verfügbar seit PHP 5.3)) können wir jetzt nachverfolgen, wo Bar definiert ist. PHP 7.0 oder höher) Enthält erweiterte Typdeklarationen, in denen Sie auch skalare Typen verwenden können (wie int oder string).

2
Machavity

Wie:

global $my_global; 
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']

ist schlechte Praxis (Like Wordpress $pagenow)... Hmmm

Bedenke dies:

$my-global = 'Transport me between functions';

ist PHP error Aber:

$GLOBALS['my-global'] = 'Transport me between functions';

is NOT error, hypens werden nicht mit "allgemeinen" vom Benutzer deklarierten Variablen kollidieren , mögen $pagenow. Und Using UPPERCASE zeigt an, dass ein Superglobal verwendet wird, das einfach im Code zu finden oder mit in Dateien zu finden ist .

Ich benutze Bindestriche, wenn ich faul bin, um Klassen von allem für eine einzige Lösung zu erstellen, wie:

$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';

Bei einer breiteren Verwendung verwende ich jedoch ONE globals als Array:

$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';

Letzteres ist für mich eine gute Übung für "Cola Light" -Ziele oder -Verwendung, anstatt jedes Mal mit Singleton-Klassen Unordnung zu erzeugen, um einige Daten "zwischenzuspeichern". Bitte machen Sie einen Kommentar, wenn ich falsch liege oder etwas Dummes hier vermisse ...

0
Jonas Lundman