PHP global in functionen

Welchen Nutzen hat das globale Schlüsselwort ?

Gibt es Gründe, eine Methode einer anderen vorzuziehen?

  • Sicherheit?
  • Performance?
  • Noch etwas?

Methode 1:

function exempleConcat($str1, $str2) { return $str1.$str2; } 

Methode 2:

 function exempleConcat() { global $str1, $str2; return $str1.$str2; } 

Wann ist es sinnvoll, global zu global ?

Für mich scheint es gefährlich zu sein … aber es kann nur ein Mangel an Wissen sein. Ich bin an dokumentierten (zB mit Code-Beispiel, Link zur Dokumentation …) technischen Gründen interessiert.

Danke im Voraus!


Kopfgeld

Dies ist eine nette allgemeine Frage zu dem Thema, ich (@Gordon) biete ein Kopfgeld an, um zusätzliche Antworten zu bekommen. Ob Ihre Antwort mit meiner übereinstimmt oder einen anderen Standpunkt vertritt, spielt keine Rolle. Da das global Thema hin und wieder auftaucht, könnten wir eine gute “kanonische” Antwort verwenden, um zu verlinken.

Globals sind böse

Dies gilt sowohl für das global Schlüsselwort als auch für alles andere, was von einem lokalen Bereich bis zum globalen Geltungsbereich reicht (Statik, Singletons, Register, Konstanten). Du willst sie nicht benutzen. Ein functionsaufruf sollte nicht auf etwas außerhalb angewiesen sein, z

 function fn() { global $foo; // never ever use that $a = SOME_CONSTANT // do not use that $b = Foo::SOME_CONSTANT; // do not use that unless self:: $c = $GLOBALS['foo']; // incl. any other superglobal ($_GET, …) $d = Foo::bar(); // any static call, incl. Singletons and Registries } 

All dies macht Ihren Code von außen abhängig. Das bedeutet, dass Sie den vollständigen globalen Status Ihrer Anwendung kennen müssen, bevor Sie diese zuverlässig aufrufen können. Die function kann ohne diese Umgebung nicht existieren.

Die Verwendung der Superglobals ist möglicherweise kein offensichtlicher Fehler, aber wenn Sie Ihren Code über eine Befehlszeile aufrufen, haben Sie weder $_GET noch $_POST . Wenn Ihr Code von diesen Eingaben abhängt, beschränken Sie sich auf eine Webumgebung. Einfach die Anfrage in ein Objekt abstrahieren und stattdessen verwenden.

Im Falle der Kopplung fest codierter classnnamen (statisch, Konstanten) kann Ihre function auch nicht existieren, ohne dass diese class verfügbar ist. Das ist weniger ein Problem, wenn es sich um classn aus demselben Namespace handelt, aber wenn Sie mit dem Mischen aus verschiedenen Namespaces beginnen, entsteht ein verwirrtes Durcheinander.

Die Wiederverwendung wird durch all die oben genannten Punkte stark behindert. So ist Unit-Testing .

Außerdem sind Ihre functionssignaturen gelogen, wenn Sie an den globalen Bereich koppeln

 function fn() 

ist ein Lügner, weil ich behaupte, ich kann diese function nennen, ohne ihr etwas zu geben. Nur wenn ich den functionskörper betrachte, den ich lerne, muss ich die Umgebung in einen bestimmten Zustand versetzen.

Wenn Ihre function das Ausführen von Argumenten erfordert, machen Sie sie explizit und übergeben Sie sie an:

 function fn($arg1, $arg2) { // do sth with $arguments } 

vermittelt deutlich von der Signatur, was es heißt, aufgerufen zu werden. Es ist nicht abhängig von der Umgebung in einem bestimmten Zustand zu sein. Du musst es nicht tun

 $arg1 = 'foo'; $arg2 = 'bar'; fn(); 

Es ist eine Frage des Einziehens (globales Schlüsselwort) gegen das Einschieben (Argumente). Wenn Sie Abhängigkeiten einfügen / injizieren, ist die function nicht mehr von außen abhängig. Wenn du fn(1) machst, brauchst du keine Variable, die irgendwo außerhalb von 1 steht. Aber wenn Sie global $one in die function ziehen, koppeln Sie den globalen Gültigkeitsbereich und erwarten, dass er irgendwo eine Variable definiert. Die function ist dann nicht mehr unabhängig.

Schlimmer noch, wenn Sie globale Variablen in Ihrer function ändern, wird Ihr Code schnell völlig unverständlich, weil Ihre functionen überall Nebenwirkungen haben.

In Ermangelung eines besseren Beispiels, überlegen

 function fn() { global $foo; echo $foo; // side effect: echo'ing $foo = 'bar'; // side effect: changing } 

Und dann tust du es

 $foo = 'foo'; fn(); // prints foo fn(); // prints bar < -- WTF!! 

Es gibt keine Möglichkeit zu sehen, dass $foo von diesen drei Zeilen geändert wurde. Warum würde die gleiche function mit denselben Argumenten auf einmal aufgerufen werden, um ihre Ausgabe zu ändern oder einen Wert im globalen Status zu ändern? Eine function sollte X für einen definierten Eingang Y tun. Immer.

Dies wird bei Verwendung von OOP sogar noch gravierender, da bei OOP die Kapselung erfolgt und durch das Erreichen des globalen Geltungsbereichs die Kapselung aufgehoben wird. All diese Singletons und Registries, die Sie in Frameworks sehen, sind Code-Gerüche, die zugunsten von Dependency Injection entfernt werden sollten. Entkoppeln Sie Ihren Code.

Mehr Ressourcen:

  • http://c2.com/cgi/wiki?GlobalVariablesAreBad
  • Wie testen Sie das Registrierungsmuster oder Singleton in PHP?
  • Fehler: Spröder globaler Staat & Singletons
  • static als schädlich angesehen
  • Warum Singletons in PHP keinen Nutzen haben
  • SOLID (objektorientiertes Design)

Der einzige Grund gegen global ist, dass die function von einem anderen Bereich abhängig ist. Dies wird sehr schnell unordentlich.

 $str1 = 'foo'; $str2 = 'bar'; $str3 = exampleConcat(); 

gegen

 $str = exampleConcat('foo', 'bar'); 

Wenn $str1 und $str2 im aufrufenden Bereich für das functionieren der function eingerichtet werden, bedeutet dies, dass Sie unnötige Abhängigkeiten einführen. Sie können diese Variablen in diesem Bereich nicht mehr umbenennen, ohne sie auch in der function und damit auch in allen anderen Bereichen, in denen Sie diese function verwenden, umzubenennen. Dies führt schnell zu Chaos, wenn Sie versuchen, Ihre Variablennamen im Auge zu behalten.

global ist ein schlechtes Muster, selbst wenn globale Dinge wie $db Ressourcen enthalten sind. Es wird der Tag kommen, an dem du $db umbenennen willst, aber nicht, weil deine ganze Anwendung vom Namen abhängt.

Der scope der Variablen einzuschränken und zu trennen ist essentiell für das Schreiben von halbwegs komplexen Anwendungen.

Globale sind unvermeidbar.

Es ist eine alte Diskussion, aber ich möchte noch einige Gedanken hinzufügen, weil ich sie in den oben erwähnten Antworten vermisse. Diese Antworten vereinfachen, was global ist zu viel und präsentieren Lösungen, die überhaupt keine Lösungen für das Problem sind. Das Problem ist: Wie ist der richtige Umgang mit einer globalen Variablen und die Verwendung des Schlüsselwortes global? Dazu müssen wir zuerst untersuchen und beschreiben, was global ist.

Schau dir diesen Code von Zend an – und bitte verstehe, dass ich nicht vorschlage, dass Zend schlecht geschrieben ist:

 class DecoratorPluginManager extends AbstractPluginManager { /** * Default set of decorators * * @var array */ protected $invokableClasses = array( 'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud', 'htmltag' => 'Zend\Tag\Cloud\Decorator\HtmlTag', 'tag' => 'Zend\Tag\Cloud\Decorator\HtmlTag', ); 

Hier gibt es viele unsichtbare Abhängigkeiten. Diese Konstanten sind eigentlich classn. Sie können require_once auch auf einigen Seiten dieses Frameworks sehen. Require_once ist eine globale Abhängigkeit und erzeugt somit externe Abhängigkeiten. Das ist für einen Rahmen unumgänglich. Wie kann man eine class wie DecoratorPluginManager ohne viel externen Code erstellen, von dem es abhängt? Es kann ohne viele Extras nicht funktionieren. Haben Sie mit dem Zend-Framework schon einmal die Implementierung einer Schnittstelle geändert? Eine Schnittstelle ist in der Tat eine globale.

Eine weitere weltweit verwendete Anwendung ist Drupal. Sie sind sehr besorgt über das richtige Design, aber wie jedes große Framework haben sie viele externe Abhängigkeiten. Schau dir die Globals auf dieser Seite an:

 /** * @file * Initiates a browser-based installation of Drupal. */ /** * Root directory of Drupal installation. */ define('DRUPAL_ROOT', getcwd()); /** * Global flag to indicate that site is in installation mode. */ define('MAINTENANCE_MODE', 'install'); // Exit early if running an incompatible PHP version to avoid fatal errors. if (version_compare(PHP_VERSION, '5.2.4') < 0) { print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the system requirements page for more information.'; exit; } // Start the installer. require_once DRUPAL_ROOT . '/includes/install.core.inc'; install_drupal(); 

Hast du jemals eine Weiterleitung auf die Login-Seite geschrieben? Das ändert einen globalen Wert. (Und dann sagst du nicht “WTF”, was ich als eine gute Reaktion auf schlechte Dokumentation deiner Anwendung betrachte.) Das Problem mit Globalen ist nicht, dass sie Globals sind, du brauchst sie, um eine sinnvolle Anwendung zu haben. Das Problem ist die Komplexität der gesamten Anwendung, die es zu einem Alptraum machen kann. Sitzungen sind globale Variablen, $ _POST ist global, DRUPAL_ROOT ist global, die includes / install.core.inc ‘ist eine nicht änderbare globale Variable. Es gibt eine große Welt außerhalb jeder function, die erforderlich ist, damit diese function ihre Aufgabe erfüllen kann.

Die Antwort von Gordon ist inkorrekt, weil er die Unabhängigkeit einer function überbewertet und eine function als Lügner bezeichnet, die Situation zu stark vereinfacht. functionen lügen nicht und wenn man sich sein Beispiel anschaut, ist die function nicht richtig ausgelegt – sein Beispiel ist ein Bug. (Übrigens stimme ich dieser Schlussfolgerung zu, dass man Code entkoppeln sollte.) Die Antwort von deceze ist nicht wirklich eine richtige Definition der Situation. functionen funktionieren immer in einem größeren Rahmen und sein Beispiel ist viel zu einfach. Wir werden ihm alle zustimmen, dass diese function völlig nutzlos ist, weil sie eine Konstante zurückgibt. Diese function ist sowieso schlechtes Design. Wenn Sie zeigen wollen, dass die Übung schlecht ist, dann kommen Sie bitte mit einem entsprechenden Beispiel. Das Umbenennen von Variablen in einer Anwendung ist keine große Sache mit einer guten IDE (oder einem Tool). Die Frage betrifft den scope der Variablen, nicht den Unterschied im scope der function. Es gibt einen geeigneten Zeitpunkt für eine function, um ihre Rolle in dem process zu erfüllen (deshalb wird sie in erster Linie erzeugt) und zu dieser richtigen Zeit kann sie die functionsweise der Anwendung als Ganzes beeinflussen und daher auch an globalen Variablen arbeiten . Die Antwort von xzyfer ist eine Aussage ohne Argumentation. Globale sind in einer Anwendung genauso vorhanden, wenn Sie prozedurale functionen oder OOP-Design haben. Die nächsten beiden Möglichkeiten, den Wert eines globalen Wertes zu ändern, sind im Wesentlichen dieselben:

 function xzy($var){ global $z; $z = $var; } function setZ($var){ $this->z = $var; } 

In beiden Fällen wird der Wert von $ z innerhalb einer bestimmten function geändert. In beiden Arten der Programmierung können Sie diese Änderungen an einer Reihe anderer Stellen im Code vornehmen. Du könntest sagen, dass du global mit $ z irgendwo aufrufen und dort ändern kannst. Ja, du kannst. Aber wirst du? Und wenn es in untauglichen Orten gemacht wird, sollte es dann nicht ein Fehler genannt werden?

Bob Fanger kommentiert xzyfer.

Sollte dann irgendjemand irgendetwas und vor allem das Stichwort “global” benutzen? Nein, aber wie jede Art von Design, versuchen Sie zu analysieren, was davon abhängt und was davon abhängt. Versuchen Sie herauszufinden, wann es sich ändert und wie es sich ändert. Globale Werte sollten nur mit den Variablen geändert werden, die sich mit jeder Anfrage / Antwort ändern können. Das heißt, nur diejenigen Variablen, die zum funktionalen Ablauf eines processes gehören, nicht zu seiner technischen Implementierung. Die Umleitung einer URL auf die Login-Seite gehört zum functionsfluss eines processes, der Implementierungsklasse, die für eine Schnittstelle zur technischen Implementierung verwendet wird. Sie können letztere während der verschiedenen Versionen der Anwendung ändern, sollten diese jedoch nicht bei jeder Anfrage / Antwort ändern.

Um zu verstehen, wenn es ein Problem ist, mit globals und dem Schlüsselwort global zu arbeiten, und wenn nicht, werde ich den nächsten Satz einführen, der von Wim de Bie kommt, wenn er über Blogs schreibt: ‘Persönlich ja, privat nein’. Wenn eine function den Wert einer globalen Variablen aufgrund ihrer eigenen functionsweise ändert, werde ich diese private Verwendung einer globalen Variablen und eines Fehlers aufrufen. Aber wenn die Änderung der globalen Variablen für die ordnungsgemäße Verarbeitung der Anwendung als Ganzes vorgenommen wird, wie die Umleitung des Benutzers auf die Anmeldeseite, dann ist das meines Erachtens möglicherweise gutes Design, per definitionem nicht schlecht und schon gar kein Anti-Muster.

Rückblickend auf die Antworten von Gordon, deceze und xzyfer: Sie alle haben als Beispiele “private yes” (und Bugs). Deshalb sind sie gegen den Einsatz von Globalen. Ich würde es auch tun. Sie kommen jedoch nicht mit “persönlichen Ja, privaten Nein’-Beispielen, wie ich es in dieser Antwort mehrmals getan habe.

Einfach gesagt, gibt es selten einen Grund zu global und nie einen guten in modernen PHP-Code IMHO. Vor allem, wenn Sie PHP 5 verwenden. Und besonders, wenn Sie objektorientierten Code entwickeln.

Globale beeinträchtigen die Wartbarkeit, Lesbarkeit und Testbarkeit von Code. Viele Verwendungen von global können und sollten durch Dependency Injection ersetzt werden oder einfach das globale Objekt als Parameter übergeben.

 function getCustomer($db, $id) { $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id)); return $row; } 

Zögern Sie nicht, globale Schlüsselwortfunktionen in PHP zu verwenden. Nimm vor allem keine Leute mit, die predigen / schreien wie Globals “böse” sind und was nicht.

Erstens, weil das, was Sie verwenden, völlig von der Situation und dem Problem abhängt, und es gibt KEINE Lösung / keinen Weg, etwas in der Codierung zu tun. Den Irrtum nicht definierbarer, subjektiver, religiöser Adjektive wie “Böses” vollständig aus den Augen zu verlieren.

Fallbeispiel:

WordPress und sein Ökosystem verwenden in ihren functionen ein globales Schlüsselwort. Sei der Code OOP oder nicht OOP.

Und ab sofort ist WordPress im Grunde 18,9% des Internets und betreibt die riesigen Megasites / Apps unzähliger Giganten, von Reuters über Sony bis zu NYT und CNN.

Und es macht es gut.

Die Verwendung von globalen Schlüsselwort-functionen befreit WordPress von MASSIVE Bloat, was angesichts seines riesigen Ökosystems passieren würde. Stellen Sie sich vor, jede function fragt nach einer Variablen, die von einem anderen Plugin benötigt wird, und gibt sie zurück. Mit Plug-in-Abhängigkeiten, die in einem Albtraum von Variablen enden würden, oder einem Albtraum von Arrays, die als Variablen übergeben wurden. Eine Hölle zu verfolgen, eine Hölle zu debuggen, eine Hölle zu entwickeln. Unglaublich großer Speicherbedarf durch Code Bloat und Variable Bloat. Schwieriger zu schreiben.

Es mag Leute geben, die kommen und WordPress kritisieren, sein Ökosystem, seine Praktiken und was in diesen Teilen passiert.

Sinnlos, da dieses Ökosystem etwa 20% des gesamten Internets ausmacht. Anscheinend funktioniert es, es macht seine Arbeit und mehr. Das bedeutet, dass das gleiche für das globale Schlüsselwort gilt.

Ein anderes gutes Beispiel ist der “iframes are evil” Fundamentalismus. Vor einem Jahrzehnt war es Häresie, Iframes zu verwenden. Und es gab Tausende von Menschen, die im Internet gegen sie predigten. Dann kommt Facebook, dann kommt soziale, jetzt iframes sind überall von “wie” Boxen zu Authentifizierung, und voila – alle halten den Mund. Es gibt diejenigen, die immer noch nicht den Mund halten – zu Recht oder zu Unrecht. Aber wissen Sie was, das Leben geht trotz solcher Meinungen weiter, und selbst diejenigen, die vor einem Jahrzehnt gegen Iframes predigen, müssen sie nun verwenden, um verschiedene soziale Apps ohne ein Wort in die eigenen Anwendungen ihrer Organisation zu integrieren.

……

Coder Fundamentalismus ist etwas sehr, sehr schlechtes. Ein kleiner Prozentsatz unter uns mag mit der angenehmen Arbeit in einem soliden monolithischen Unternehmen geehrt werden, das genug Einfluss hat, um den ständigen Wandel in der Informationstechnologie und den damit verbundenen Druck in Bezug auf Wettbewerb, Zeit, Budget und andere Überlegungen zu ertragen und daher praktizieren kann Fundamentalismus und strikte Einhaltung der wahrgenommenen “Übel” oder “Güter”. Komfortable Positionen, die an alte Zeiten erinnern, sind dies, selbst wenn die Bewohner jung sind.

Für die Mehrheit jedoch ist die Welt eine sich ständig verändernde Welt, in der sie offen und praktisch sein müssen. Es gibt keinen Platz für Fundamentalismus, lassen Sie unverschämte Stichworte wie “böse” in den vordersten Reihen der Informationstechnologie zurück.

Verwenden Sie einfach das, was den besten Sinn für das Problem AT HAND mit entsprechenden Überlegungen für kurz-, mittel- und langfristige Zukunft macht. Scheuen Sie sich nicht davor, irgendein Merkmal oder Ansatz zu verwenden, da es unter allen gegebenen Coder-Untergruppen eine wuchernde ideologische Feindseligkeit dagegen hat.

Sie machen Ihre Arbeit nicht. Du wirst. Handle nach deinen Umständen.

Ich denke, dass jeder ziemlich viel über die negativen Aspekte von Globals erklärt hat. Also werde ich sowohl die positiven als auch die statementen für die korrekte Verwendung von Globals hinzufügen:

  1. Der Hauptzweck von Globals bestand darin, Informationen zwischen functionen auszutauschen. Zurück, als es nichts wie eine class gab, bestand PHP-Code aus einer Reihe von functionen. Manchmal müssten Sie Informationen zwischen functionen austauschen. In der Regel wurde das globale System verwendet, um Daten zu korrumpieren, indem sie global gemacht wurden.

    Nun, bevor ein glücklicher Glückspilz einen Kommentar über die Abhängigkeitsinjektion beginnt, möchte ich Sie fragen, wie der Benutzer einer function wie beispiel get_post(1) alle Abhängigkeiten der function kennen würde. Bedenken Sie auch, dass Abhängigkeiten von denen abweichen können
    Version zu Version und Server zu Server. Das Hauptproblem bei der Abhängigkeitsinjektion sind Abhängigkeiten, die vorher bekannt sein müssen. In einer Situation, in der dies nicht möglich ist oder unerwünschte globale Variablen der einzige Weg waren, um dieses Ziel zu erreichen.

    Durch die Erstellung der class können nun allgemeine functionen einfach in einer class gruppiert und Daten gemeinsam genutzt werden. Durch Implementierungen wie Mediatoren können sogar unabhängige Objekte Informationen teilen. Dies ist nicht mehr notwendig.

  2. Eine andere Verwendung für Globals ist die Konfiguration. Meistens am Anfang eines Skripts, bevor Autoloader geladen wurden, databaseverbindungen hergestellt wurden usw.

    Während des Ladens von Ressourcen können globale Daten verwendet werden, um Daten zu konfigurieren (z. B. welche database verwendet werden soll, wo sich Bibliotheksdateien befinden, die URL des Servers usw.). Der beste Weg dazu ist die Verwendung der function define() , da diese Werte sich nicht oft ändern und leicht in eine Konfigurationsdatei eingefügt werden können.

  3. Die letzte Verwendung für Globals besteht darin, gemeinsame Daten (dh CRLF, IMAGE_DIR, IMAGE_DIR_URL), für Menschen lesbare Statusflags (dh ITERATOR_IS_RECURSIVE) zu speichern. Globals werden hier verwendet, um Informationen zu speichern, die anwendungsweit verwendet werden sollen, sodass sie geändert werden können und diese Änderungen anwendungsweit erscheinen.

  4. Das Singleton-Muster wurde in PHP während php4 populär, als jede Instanz eines Objekts Speicher belegte. Das Singleton half beim Speichern von RAM, indem nur eine Instanz eines Objekts erstellt wurde. Vor den Referenzen wäre sogar die Abhängigkeitsinjektion eine schlechte Idee gewesen.

    Die neue php-Implementierung von Objekten aus PHP 5.4+ kümmert sich um die meisten dieser Probleme, mit denen Sie Objekte mit wenig oder gar keinen Kosten sicher weiterreichen können. Dies ist nicht mehr notwendig.

    Eine weitere Verwendung für Singletons ist die spezielle Instanz, bei der immer nur eine Instanz eines Objekts existieren muss, diese Instanz vor / nach der Skriptausführung vorhanden sein kann und dieses Objekt von verschiedenen Skripten / Servern / Sprachen usw. gemeinsam genutzt wird. Hier triggers ein Singleton-Muster die Lösung ganz gut.

Abschließend, wenn Sie in Position 1, 2 oder 3 sind, dann wäre die Verwendung einer globalen sinnvoll. In anderen Situationen sollte jedoch Methode 1 verwendet werden.

Fühlen Sie sich frei, irgendwelche anderen Fälle zu aktualisieren, in denen globals benutzt werden sollte.

Es macht keinen Sinn, mit dem Schlüsselwort global eine Concat-function zu erstellen.

Es wird verwendet, um auf globale Variablen wie ein databaseobjekt zuzugreifen.

Beispiel:

 function getCustomer($id) { global $db; $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id)); return $row; } 

Es kann als eine Variation des Singleton-Musters verwendet werden