Namespaces Übersicht über Namespaces Übersicht Was sind Namespaces? Im weitesten Sinne bieten Namespaces eine Möglichkeit, verschiedene Gegenstände zu kapseln. Dies kann man als abstraktes Konzept an vielen Dingen beobachten. In einem Betriebssystem dienen zum Beispiel Verzeichnisse dazu, um zusammengehörige Dateien zu gruppieren, und dienen als Namespace für die beinhalteten Dateien. In einem konkreten Beispiel kann die Datei foo.txt sowohl im Verzeichnis /home/greg als auch in /home/other existieren, aber es können keine zwei Varianten der Datei foo.txt im gleichen Verzeichnis existieren. Um auf die Datei foo.txt von außerhalb des Verzeichnisses /home/greg zuzugreifen, muss man zusätzlich dem Verzeichnisnamen den Dateinamen und ein Trennzeichen voranstellen, um /home/greg/foo.txt zu erhalten. Das gleiche Prinzip streckt sich auf Namespaces in der Programmierwelt aus. In der Welt von PHP wurden Namespaces entworfen, um zwei Probleme zu lösen, auf die die Autoren von Bibliotheken und Anwendungen stoßen, wenn sie wiederverwendbare Codeelemente wie Klassen und Funktionen entwickeln: Namenskollisionen zwischen eigenem Code und internen PHP-Klassen/Funktionen/Konstanten oder Klassen/Funktionen/Konstanten von Drittanbietern. Die Möglichkeit, einen Alias (oder einen Kurznamen) für Sehr_Lange_Namen einzuführen, die geschaffen wurde, um das erste Problem zu umgehen. Damit kann man die Lesbarkeit des Quellcodes erhöhen. PHP-Namespaces bieten eine Möglichkeit, zusammengehörige Klassen, Interfaces, Funktionen und Konstanten zusammenzufassen. Dies ist ein Beispiel für die Namespace-Syntax in PHP: Beispiel für Namespace-Syntax ]]> Bei Namespace-Namen wird nicht zwischen Groß- und Kleinschreibung unterschieden. Der Namespace PHP, sowie zusammengesetzte Namen, die mit dieser Bezeichnung beginnen (wie &zb; PHP\Classes), sind zur internen Verwendung in der Sprache reserviert und sollten im eigenen Programmcode nicht verwendet werden. Namespaces definieren Namespaces Obwohl jeder gültige PHP-Quellcode in Namespaces eingeschlossen werden kann, werden nur die folgenden Arten von Code von Namespaces beeinflusst: Klassen (inklusive abstrakter Klassen, Traits und Enums), Interfaces, Funktionen und Konstanten. Namespaces werden mit dem Schlüsselwort namespace definiert. Eine Datei, die einen Namespace beinhaltet, muss den Namespace am Anfang der Datei vor jeglichem anderen Code deklarieren - mit Ausnahme des -Schlüsselwortes. Einen einzelnen Namespace deklarieren ]]> Vollständig qualifizierte Namen (&dh; Namen, die mit einem Rückwärtsschrägstrich beginnen) sind in Namensraumdeklarationen nicht erlaubt, weil solche Konstrukte als relative Namensraumausdrücke interpretiert werden. Der einzige Quellcode, der vor einer Namespacedeklaration stehen darf, ist der declare-Ausdruck, der die Kodierung der Quellcodedatei definiert. Gleichzeitig darf kein Nicht-PHP-Code vor einer Namespacedeklaration stehen - auch keine zusätzlichen Leerzeichen, Zeilenumbrüche oder Tabulatoren. Einen einzelnen Namespace deklarieren ]]> Zusätzlich darf - im Gegensatz zu anderen PHP-Konstrukten - der selbe Namespace in mehreren Dateien definiert werden, womit man den Inhalt eines Namespaces im Dateisystem aufteilen kann. Unter-Namespaces deklarieren Unter-Namespaces Ähnlich wie Verzeichnisse und Dateien hat ein PHP-Namespace auch die Möglichkeit, eine Hierarchie von Namespacenamen zu beinhalten. Ein Namespace kann also mit Unterebenen definiert werden: Einen einzelnen Namespace mit einer Hierarchie deklarieren ]]> Das obige Beispiel erzeugt eine Konstante MyProject\Sub\Level\CONNECT_OK, die Klasse MyProject\Sub\Level\Connection und die Funktion MyProject\Sub\Level\connect. Mehrere Namespaces in derselben Datei definieren Mehrere Namespaces in derselben Datei definieren Es können auch mehrere Namespaces in derselben Datei definiert werden. Es gibt hierfür zwei mögliche Schreibweisen: Mehrere Namespaces definieren, einfache Kombinationssyntax ]]> Diese Syntax ist nicht die empfohlene Syntax, um mehrere Namespaces in einer einzigen Datei zusammenzuführen. Stattdessen wird die geklammerte Syntax empfohlen. Mehrere Namespaces definieren, geklammerte Syntax ]]> Es wird stark von der Programmierpraxis, mehrere Namespaces in einer Datei zu definieren, abgeraten. Der wichtigste Einsatzzweck dieser Möglichkeit ist es, mehrere PHP-Skripte in derselben Datei zusammenzuführen. Um Code ohne Namensräume mit solchem mit Namensräumen zusammenzuführen, wird nur die geklammerte Syntax unterstützt. Globaler Code sollte in einem Namespace-Statement ohne Namespace eingeschlossen werden: Mehrere Namespaces und Code ohne Namespace deklarieren ]]> Es darf kein PHP-Code außerhalb der Namespace-Klammern existieren, abgesehen von einem beginnenden declare-Ausdruck. Mehrere Namespaces und Code ohne Namespace deklarieren ]]> Namespaces verwenden: Grundlagen Grundlagen Bevor die Verwendung von Namespaces besprochen wird, ist es wichtig zu verstehen, woher PHP weiß, welches Element mit Namespace vom Code angefordert wird. Eine einfache Analogie kann zwischen PHP-Namensräumen und einem Dateisystem gesehen werden. Es gibt drei Möglichkeiten, mit denen man auf eine Datei in einem Dateisystem zugreifen kann: Relative Dateinamen wie foo.txt. Dies wird zu aktuellesVerzeichnis/foo.txt aufgelöst, wenn aktuellesVerzeichnis das gerade geöffnete Verzeichnis ist. Wenn also das aktuelle Verzeichnis /home/foo ist, so wird dies als /home/foo/foo.txt aufgelöst. Relative Pfade wie unterVerzeichnis/foo.txt. Dies wird zu aktuellesVerzeichnis/unterVerzeichnis/foo.txt aufgelöst. Absolute Pfadangaben wie /main/foo.txt. Dies wird zu /main/foo.txt aufgelöst. Das gleiche Prinzip kann auf Elemente mit Namespaces in PHP angewandt werden. Zum Beispiel kann eine Klasse auf drei Arten angesprochen werden: Unqualifizierte Namen oder ein Klassenname ohne Präfix, wie etwa $a = new foo(); oder foo::staticmethod();. Falls der aktuelle Namespace aktuellerNamespace ist, so wird dies zu aktuellerNamespace\foo aufgelöst. Ist der Code globaler Code ohne Namespaces, so wird dies zu foo aufgelöst. Es gibt eine Ausnahme hierzu: Unqualifizierte Namen für Funktionen und Konstanten werden zu globalen Funktionen und Konstanten aufgelöst, wenn die Funktion oder Konstante im Namespace nicht definiert ist. Siehe auch Namespaces verwenden: Rückgriff auf globale Funktion/Konstante für weitere Details. Qualifizierte Namen oder ein Klassenname mit Präfix, wie etwa $a = new unterNamespace\foo(); oder unterNamespace\foo::staticmethod();. Wenn der aktuelle Namespace aktuellerNamespace ist, so wird dies als aktuellerNamespace\unterNamespace\foo verstanden. Wenn der Code global und ohne Namespaces ist, so wird dies zu unterNamespace\foo aufgelöst. Vollständig qualifizierte Namen oder Namen mit globalem Präfixoperator wie $a = new \aktuellerNamespace\foo(); oder \aktuellerNamespace\foo::staticmethod();. Dies wird immer wörtlich wie der im Code angegebene Name verstanden, also aktuellerNamespace\foo. Hier ein Beispiel für die drei Schreibweisen in tatsächlichem Code: file1.php ]]> file2.php ]]> Beachten Sie, dass für den Zugriff auf jede globale Klasse, Funktion oder Konstante9 auch ein vollständig qualifizierter Name verwendet werden kann, wie &zb; \strlen, \Exception oder \INI_ALL. Zugriff auf globale Klassen, Funktionen und Konstanten aus einem Namespace ]]> Namespaces und dynamische Sprachfeatures Namespaces und dynamische Sprachfeatures Die Implementierung von Namespaces in PHP ist stark von seinen Eigenschaften als Programmiersprache mit dynamischen Features beeinflusst. Man kann also den folgenden Code in Code mit Namespaces umformen: Dynamischer Zugriff auf Elemente example1.php: ]]> Um diesen Code umzuformen, muss man den vollständig qualifizierten Namen (Klassenname mit namespace-Präfix) verwenden. Beachten Sie, dass, weil es keinen Unterschied zwischen einem qualifizierten und vollständig qualifizierten Namen innerhalb eines dynamischen Klassen-, Funktions- oder Konstantennamen gibt, der führende Backslash nicht notwendigerweise angegeben werden muss. Dynamischer Zugriff auf Elemente mit Namespace ]]> Bitte lesen Sie auch den Hinweis zum Escaping von Namespacenamen in Strings. Das Schlüsselwort namespace und die magische Konstante __NAMESPACE__ Schlüsselwort namespace und __NAMESPACE__ PHP unterstützt zwei Arten des abstrakten Zugriffs auf Elemente innerhalb eines Namespaces, die magische Konstante __NAMESPACE__ und das Schlüsselwort namespace. Der Wert von __NAMESPACE__ ist ein String, der den Namen des aktuellen Namespace beinhaltet. In globalem Code ohne Namespaces beinhaltet dies einen leeren String. __NAMESPACE__-Beispiel, Code mit Namespace ]]> __NAMESPACE__-Beispiel, globaler Code ]]> Die Konstante __NAMESPACE__ ist nützlich, um dynamische Namen zu konstruieren, zum Beispiel: __NAMESPACE__ zur dynamischen Namenszusammensetzung verwenden ]]> Das Schlüsselwort namespace kann verwendet werden, um explizit ein Element des aktuellen Namespaces oder eines untergeordneten Namespaces anzufordern. Es ist das äquivalent der Namespaces zum self-Operator für Klassen. Der namespace-Operator, innerhalb eines Namespace ]]> Der namespace-Operator, in globalem Code ]]> Namespaces verwenden: Aliase/Importieren Aliase und Importieren Die Möglichkeit, auf vollständig qualifizierte Namen mit einem Alias (Importieren) zuzugreifen, ist ein wichtiges Feature von Namespaces. Dies ist ähnlich wie die Möglichkeit von Unix-basierten Dateisystemen einen symbolischen Link auf eine Datei oder ein Verzeichnis anzulegen. PHP unterstützt das Vergeben von Aliasen (Importe) für Konstanten, Funktionen, Klassen, Interfaces, Traits, Aufzählungen (Enums) und Namespaces. Ein Alias wird mittels des use-Operators angelegt. Hier ein Beispiel, welches alle fünf Arten von Importen zeigt: Aliase/Importieren mit dem use-Operator ]]> Beachten Sie, dass für Namen von Namespaces (vollständig qualifizierte Namespacenamen mit einem Namensraumseparator, wie Foo\Bar, im Gegensatz zu globalen Namen ohne Separator, wie FooBar) der führende Backslash nicht notwendig und nicht empfohlen ist, weil importierte Namen vollständig qualifiziert sein müssen und nicht relativ zum aktuellen Namespace verarbeitet werden. PHP unterstützt zusätzlich auch eine komfortable Kurzsyntax, mit der mehrere use-Ausdrücke in der gleichen Zeile erscheinen können. Aliase/Importieren mit dem use-Operator, mehrere use-Ausdrücke kombiniert ]]> Importieren wird zur Kompilierungszeit ausgeführt und hat daher keinen Einfluss auf dynamische Klassen-, Funktions- oder Konstantennamen. Importieren und dynamische Namen ]]> Zusätzlich beeinflusst das Importieren nur unqualifizierte und qualifizierte Namen. Vollständig qualifizierte Namen sind absolut und werden von Importen nicht beeinflusst. Importieren und vollständig qualifizierte Namen ]]> Gültigkeitsbereiche für Importe Das Schlüsselwort use muss im äußersten Gültigkeitsbereich (dem globalen Gültigkeitsbereich) oder innerhalb einer Namespace-Deklaration angegeben werden. Das ist darin begründet, dass Importe zur Kompilierungszeit und nicht zur Laufzeit durchgeführt werden und daher nicht in einem anderen Gültigkeitsbereich liegen dürfen. Das folgende Beispiel zeigt eine ungültige Verwendung des use-Schlüsselwortes: Ungültige Importregel ]]> Importregeln sind auf Dateibasis gültig, das heißt eine eingebundene Datei wird NICHT die Importregeln der einbindenden Datei erben. Gruppierte <literal>use</literal> Deklarationen Klassen, Funktionen und Konstanten, die aus dem gleichen Namespace importiert werden, in einer einzigen &use.namespace; Anweisung gruppiert werden. Globaler Namensraum Globaler Namensraum Ohne die Definition eines Namespace werden alle Klassen- und Funktionsdefinitionen im globalen Namensraum platziert, so wie dies auch in PHP geschah bevor Namespaces unterstützt wurden. Wenn man dem Namen ein \ voranstellt, so spezifiziert man, dass der Name dem globalen Namensraum angehört, auch wenn man sich im Kontext eines Namensraumes befindet. Verwenden der Spezifikation des globalen Namensraumes ]]> Namespaces verwenden: Rückgriff auf den globalen Namespace für Funktionen und Konstanten Rückgriff auf den globalen Namespace Wenn PHP innerhalb eines Namespace auf einen unqualifizierten Namen für einen Klassen-, Funktions- oder Konstantennamen trifft, so werden diese mit unterschiedlichen Prioritäten aufgelöst. Klassennamen werden immer auf den aktuellen Namespace aufgelöst. Um also auf interne Klassen oder Benutzerklassen ohne Namespace zuzugreifen, muss man diese mit ihrem vollständig qualifizierten Namen ansprechen: Zugriff auf globale Klasse innerhalb eines Namespace ]]> Für Funktionen und Konstanten wird PHP auf globale Funktionen oder Konstanten zurückgreifen, wenn eine Funktion oder Konstante im Namespace nicht existiert. Rückgriff auf globale Funktionen/Konstanten innerhalb eines Namespace ]]> Regeln für Namensauflösung Regeln für Namensauflösung Hier einige wichtige Definitionen für die Zwecke der Namensauflösungsregeln: Namespace-Namen-Definitionen Unqualifizierter Name Dies ist ein Bezeichner ohne einen Namespaceseparator, &zb; Foo Qualifizierter Name Dies ist ein Bezeichner mit einem Namespaceseparator, &zb; Foo\Bar Vollständig qualifizierter Name Dies ist ein Bezeichner mit einem Namespaceseparator, der mit einem Namespaceseparator beginnt, &zb; \Foo\Bar. Der Namespace namespace\Foo ist ebenfalls ein vollständig qualifizierter Name. Relativer Name Dies ist ein Bezeichner, der mit namespace beginnt, wie etwa namespace\Foo\Bar. Namen werden gemäß den folgenden Regeln aufgelöst: Vollständig qualifizierte Namens werden immer zu dem Namen ohne führenden Namensraumtrenner aufgelöst. \A\B wird &zb; zu A\B aufgelöst. Relative Namen werden immer zu dem Namen aufgelöst, in dem namespace durch den aktuellen Namensraum ersetzt wurde. Taucht der Namen im globalen Geltungsbereich auf, wird das namespace\-Präfix entfernt. Beispielsweise wird namespace\A innerhalb des Namensraums X\Y zu X\Y\A aufgelöst. Derselbe Name im globalen Geltungsbereich wird zu A aufgelöst. Für qualifizierte Namen wird das erste Segment des Namens gemäß der aktuellen Klassen-/Namensraum-Importtabelle übersetzt. Wird beispielsweise der Namensraum A\B\C als C importiert, wird der Name C\D\E zu A\B\C\D\E übersetzt. Wenn für qualifizierte Namen keine Importregel zutrifft, wird der aktuelle Namensraum dem Namen vorangestellt. Beispielsweise wird der Name C\D\E innerhalb des Namensraums A\B zu A\B\C\D\E aufgelöst. Für unqualifizierte Namen wird der Name gemäß der aktuellen Importtabelle für die betreffende Symboltabelle übersetzt. Das bedeutet, dass klassenartige Namen gemäß der Klassen-/Namensraum-Importtabelle, Funktionsnamen gemäß der Funktions-Importtabelle und Konstantennamen gemäß der Konstanten-Importtabelle übersetzt werden. Beispielsweise wird nach use A\B\C; eine Verwendung wie etwa new C() zum Namen A\B\C() aufgelöst. Analog wird nach use function A\B\foo; eine Verwendung wie etwa foo() zum Namen A\B\foo aufgelöst. Wenn für unqualifizierte Namen keine Importregel zutrifft, und sich der Name auf ein klassenartiges Symbol bezieht, wird der aktuelle Namensraum vorangestellt. Beispielsweise wird new C() innerhalb des Namensraums A\B zum Namen A\B\C aufgelöst. Wenn für unqualifizierte Namen keine Importregel zutrifft, und sich der Name auf eine Funktion oder Konstante bezieht, und der Code sich außerhalb des globalen Geltungsbereichs befindet, wird der Name zur Laufzeit aufgelöst. Angenommen der Code befindet sich im Namensraum A\B, wird im folgenden erläutert, wie der Aufruf einer Funktion foo() aufgelöst wird: Zuerst wird nach der Funktion im aktuellen Namespace gesucht: A\B\foo(). Es wird versucht, die Funktion foo() im globalen Namensraum zu finden und aufzurufen. Illustration der Namensauflösung ]]> FAQ: Dinge, die Sie über Namespaces wissen sollten FAQ Diese häufig gestellten Fragen (FAQ) wurden in zwei Abschnitte aufgeteilt: allgemeine Fragen und einige Implementierungsdetails, deren vollständiges Verständnis hilfreich sein kann. Zuerst die allgemeinen Fragen. Wenn ich keine Namespaces verwende, sollte mich das alles hier überhaupt interessieren? Wie verwende ich interne oder globale Klassen in einem Namespace? Wie verwende ich Klassen, Funktionen oder Konstanten mit Namespaces in ihrem eigenen Namespace? Wie wird ein Name wie \mein\name oder \name aufgelöst? Wie wird ein Name wie mein\name aufgelöst? Wie wird ein unqualifizierter Name wie name aufgelöst? Wie wird ein unqualifizierter Funktions- oder Konstantenname wie name aufgelöst? Es gibt einige Implementierungsdetails von Namespaces, deren Verständnis hilfreich ist. Importierte Namen dürfen keine Konflikte mit Klassennamen in der gleichen Datei erzeugen. Verschachtelte Namespaces sind nicht erlaubt. Dynamische Namespacenamen sollten den Backslash escapen. Zugriff auf undefinierte Konstanten mit Backslashes beendet das Skript mit einem fatal error. Die speziellen Konstanten &null;, &true; und &false; können nicht überschrieben werden. Wenn ich keine Namespaces verwende, sollte mich das alles hier überhaupt interessieren? Nein. Namespaces haben keinerlei Einfluss auf bereits bestehenden Code oder irgendwelchen Code der noch geschrieben wird, der keine Namespaces verwendet. Sie können folgenden Code schreiben, wenn Sie dies wünschen: Zugriff auf globale Klassen außerhalb eines Namespace ]]> Dies ist äquivalent zu: Zugriff auf globale Klassen außerhalb eines Namespace ]]> Wie verwende ich interne oder globale Klassen in einem Namespace? Zugriff auf interne Klassen in Namespaces ]]> Wie verwende ich Klassen, Funktionen oder Konstanten mit Namespaces in ihrem eigenen Namespace? Zugriff auf interne Klassen, Funktionen oder Konstanten in Namespaces ]]> Wie wird ein Name wie <literal>\mein\name</literal> oder <literal>\name</literal> aufgelöst? Namen, die mit einem \ beginnen, werden immer zu exakt dem aufgelöst wie sie aussehen. \mein\name ist also tatsächlich \mein\name und \Exception ist Exception. Vollständig qualifizierte Namen ]]> Wie wird ein Name wie <literal>mein\name</literal> aufgelöst? Namen, die einen Backslash beinhalten, aber nicht mit einem Backslash beginnen, wie &zb; mein\name, können auf zwei verschiedene Arten aufgelöst werden. Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen definiert, so dass dieser mein heißen soll, dann wird dieser Alias für das mein in mein\name angewandt. Andernfalls wird der aktuelle Namespace vor mein\name vorangestellt. Qualifizierte Namen ]]> Wie wird ein unqualifizierter Name wie <literal>name</literal> aufgelöst? Klassennamen, die keinen Backslash beinhalten, wie &zb; name, können auf zwei Arten aufgelöst werden. Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen definiert, so dass dieser name heißen soll, dann wird dieser Alias angewandt. Andernfalls wird der aktuelle Namespace name vorangestellt. Unqualifizierter Klassennamen ]]> Wie wird ein unqualifizierter Funktions- oder Konstantenname wie <literal>name</literal> aufgelöst? Funktions- oder Konstantennamen, die keinen Backslash beinhalten, wie &zb; name, können auf zwei verschiedene Arten aufgelöst werden. Zuerst wird der aktuelle Namespace dem name vorangestellt. Wenn die Konstante oder Funktion name im aktuellen Namensraum nicht existiert, so wird die globale Konstante oder Funktion name verwendet, wenn sie existiert. Unqualifizierte Funktions- oder Konstantennamen ]]> Importierte Namen dürfen keine Konflikte mit Klassennamen in der gleichen Datei erzeugen. Die folgende Kombination von Skripten ist gültig: file1.php ]]> anderes.php ]]> file2.php ]]> Es gibt hier, trotzdem es eine Klasse MyClass im Namespace mein\zeug gibt, keinen Namenskonflikt, weil die Definition der Klasse MyClass sich in einer anderen Datei befindet. Das nächste Beispiel erzeugt hingegen einen fatal error wegen eines Namenskonflikts, weil MyClass in derselben Datei definiert wird, die auch den use-Ausdruck beinhaltet. ]]> Verschachtelte Namespaces sind nicht erlaubt. PHP erlaubt das Verschachteln von Namespaces nicht. ]]> Es ist jedoch leicht möglich, verschachtelte Namespaces zu simulieren: ]]> Dynamische Namespacenamen sollten den Backslash escapen. Es ist wichtig zu bemerken, dass ein Backslash in Strings als Escape-Zeichen verwendet wird und daher immer verdoppelt werden sollte, wenn er in einem String verwendet wird. Andernfalls besteht das Risiko ungewollter Auswirkungen: Gefahren von Namespacenamen in Strings mit doppelten Anführungszeichen ]]> Innerhalb eines Strings, der von einfachen Anführungszeichen umschlossen ist, ist es deutlich ungefährlicher, die Backslash-Escape-Sequenz zu verwenden. Es wird dennoch empfohlen, Backslashes in allen Strings zu escapen. Zugriff auf undefinierte Konstanten mit Backslashes beendet das Skript mit einem fatal error. Jeder Zugriff auf eine Konstante mit unqualifiziertem Namen, wie FOO, wird eine Notice erzeugen, welche erklärt, dass PHP angenommen hat, dass FOO der Wert der Konstante sei. Jede Konstante, qualifiziert oder vollständig qualifiziert, deren Name einen Backslash enthält, wird einen fatal error hervorrufen, wenn sie nicht gefunden wurde. Undefinierte Konstanten ]]> Die speziellen Konstanten &null;, &true; und &false; können nicht überschrieben werden. Jeder Versuch, eine Konstante in einem Namespace zu definieren, die eine der speziellen, eingebauten Konstanten ist, wird einen fatal error hervorrufen. Spezielle Konstanten ]]>