Frage 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 auf diese Variable in einer Funktion zugreifen möchte, tue ich global $var;.

Ist das eine schlechte Übung?


75
2017-10-13 01:19


Ursprung


Antworten:


Wenn Menschen über globale Variablen in anderen Sprachen sprechen, bedeutet das etwas anderes als in PHP. Das liegt daran, dass Variablen nicht sind Ja wirklich global in PHP. Der Umfang eines typischen PHP-Programms ist eine HTTP-Anfrage. Session-Variablen haben tatsächlich einen größeren Umfang als PHP "globale" Variablen, weil sie typischerweise viele HTTP-Anfragen umfassen.

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

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

Sehen Rückrufe für mehr.

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

Sorgen Sie sich nicht zu sehr darum, Standards oder Konstrukte aus verschiedenen Sprachen auf PHP anzuwenden. Ein weiterer häufiger Fehler ist der Versuch, PHP in eine reine OOP-Sprache zu verwandeln, indem Objektmodelle auf alles gelegt werden.

Wie alles andere auch, verwenden Sie "globale" Variablen, prozeduralen Code, ein bestimmtes Framework und OOP, weil es sinnvoll ist, ein Problem löst, die Menge an Code reduziert, die Sie schreiben müssen, oder einfacher zu verstehen, nicht weil Sie denken Du solltest.


86
2017-10-13 01:22



Wenn globale Variablen nicht sorgfältig verwendet werden, können Probleme schwerer zu finden sein. Angenommen, Sie fordern ein PHP-Skript an und erhalten eine Warnung, dass Sie versuchen, auf einen Index eines Arrays zuzugreifen, das in einer Funktion nicht existiert.

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. Es könnte ein Problem mit einer Eingabe für die Funktion sein, so dass Sie die Stellen überprüfen, 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 Sie müssen nicht nur herausfinden, in welcher Reihenfolge auf diese Verweise auf die globale Variable zugegriffen wird.

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


22
2017-10-13 03:34



Ich stimme mit Cletus überein. 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 um den Code herum.

freundliche Grüße, Don


15
2017-10-13 01:39



Wer kann gegen Erfahrung, College-Abschluss und Software-Engineering argumentieren? Nicht ich. Ich würde nur sagen, dass ich bei der Entwicklung von objektorientierten Einzelseiten-PHP-Anwendungen mehr Spaß habe, wenn ich weiß, dass ich die gesamte Sache von Grund auf neu erstellen kann, ohne mich um Namespace-Kollisionen kümmern zu müssen. Bauen von Grund auf ist etwas, was viele Leute nicht mehr tun. Sie haben einen Job, eine Frist, einen Bonus oder einen Ruf, um den sie sich kümmern müssen. Diese Typen neigen dazu, so viel vorgefertigten Code mit hohen Einsätzen zu verwenden, dass sie 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 wollen Viel Spaß und etwas Arbeit machen.

Wenn das bedeutet, einige Variablen (<10) im globalen Namespace zu verwenden, die nur im globalen Bereich eines Programms verwendet werden, sei es so. Ja, ja, MVC, Abhängigkeitsinjektion, externer Code, blah, blah, blah, blah. Aber wenn Sie 99,99% Ihres Codes in Namespaces und Klassen enthalten haben und externer Code sandboxed ist, wird die Welt nicht enden (ich wiederhole, die Welt wird nicht enden), wenn Sie eine globale Variable verwenden.

Generell würde ich nicht sagen, globale Variablen zu verwenden ist schlechte Übung. Ich würde sagen, dass globale Variablen (Flags usw.) außerhalb des globalen Bereichs eines Programms verwendet werden Ärger suchen und (auf lange Sicht) schlecht beraten weil Sie ihre Zustände ziemlich leicht aus den Augen verlieren können. Das würde ich auch sagen je mehr du lernst, desto weniger abhängig wirst du sein auf globale Variablen, weil Sie die "Freude" erfahren haben, Bugs zu finden, die mit ihrer Verwendung verbunden sind. Dies allein wird Sie anreizen, einen anderen Weg zu finden, um das gleiche Problem zu lösen. Zufälligerweise tendiert dies dazu, PHP-Leute dazu zu bringen, zu lernen, wie man Namespaces und Klassen verwendet (statische Mitglieder, etc ...).

Der Bereich der Informatik ist riesig. Wenn wir alle davon abschrecken, etwas zu tun, weil wir es beschriften Schlecht, dann verlieren sie den Spaß daran, die Gründe hinter dem Label wirklich zu verstehen.

Verwenden Sie globale Variablen, wenn Sie müssen, aber dann sehen Sie, ob Sie das Problem ohne sie lösen können. Kollisionen, Tests und Debugging bedeuten mehr, wenn Sie die wahre Natur des Problems genau verstehen und nicht nur eine Beschreibung des Problems.


4
2018-01-10 16:47



Wie:

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

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

Überlegen Sie dies:

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

ist PHP Fehler Aber:

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

ist NICHT Error, Hyphen werden nicht kollidieren mit "common" user deklarierten Variablen, wie $pagenow. Und die Verwendung von UPPERCASE zeigt an, dass ein Superglobal verwendet wird, der einfach im Code zu finden ist oder mit dem Track verfolgt werden kann finde in Dateien

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

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

Aber in Fällen einer breiteren Verwendung verwende ich EIN 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, gute Übung auf "Cola Light" Objektive oder verwenden Sie statt Clutter mit Singleton-Klassen jedes Mal, um einige Daten zu "cachen". Bitte machen Sie einen Kommentar wenn ich falsch liege oder etwas Dummes hier vermisse ...


0
2017-10-17 05:03



Repotiert 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 hier offensichtlich

Wo war das? $bob komme aus?

Bist du verwirrt? Gut. Sie haben gerade erfahren, warum Globals verwirrend sind und als schlechte Übung betrachtet werden. Wenn dies ein echtes Programm ist, ist es das nächste bisschen Spaß, alle Instanzen von $bobund hoffe, du findest den richtigen (das wird schlimmer wenn $bob wird überall benutzt). Schlimmer noch, wenn jemand anders geht und definiert $bob (oder Sie haben diese Variable vergessen und wiederverwendet) Ihr Code kann brechen (im obigen Codebeispiel würde das falsche Objekt oder überhaupt kein Objekt einen schwerwiegenden Fehler verursachen). Da praktisch alle PHP-Programme Code verwenden wie include('file.php'); Ihr Job, der Code wie diesen aufrechterhält, wird exponentiell härter, je mehr Dateien Sie hinzufügen.

Wie vermeiden wir Globals?

Der beste Weg, um Globals zu vermeiden, ist eine Philosophie namens Abhängigkeitsspritze. Hier übergeben wir die Werkzeuge, die wir brauchen, in die Funktion oder Klasse.

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

Das ist viel einfacher zu verstehen und zu pflegen. Es gibt keine Vermutung wo $bob wurde eingerichtet, weil der Anrufer dafür verantwortlich ist, das zu wissen (es gibt uns das, was wir wissen müssen). Besser noch, wir können es gebrauchen Typdeklarationen um einzuschränken, was passiert wird. Das wissen wir $bob ist entweder eine Instanz der Bar Klasse oder eine Instanz eines Kindes von BarWir 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 ist definiert. PHP 7.0 oder höher enthält erweiterte Typdeklarationen, in denen Sie auch Skalartypen (wie int oder string).


-2
2017-08-24 00:21