PHP-Namespace (Namespace) wurde in PHP 5.3 hinzugefügt. Wenn Sie C# und Java studiert haben, ist Namespace nichts Neues. Allerdings hat es in PHP immer noch eine sehr wichtige Bedeutung.
PHP-Namespaces können die folgenden zwei Arten von Problemen lösen:
Namenskonflikte zwischen vom Benutzer geschriebenem Code und internen Klassen/Funktionen/Konstanten von PHP oder Klassen/Funktionen/Konstanten von Drittanbietern.
Erstellen Sie einen Aliasnamen (oder Kurznamen) für einen sehr langen Bezeichnernamen (der normalerweise zur Linderung des ersten Problemtyps definiert wird), um die Lesbarkeit des Quellcodes zu verbessern.
Standardmäßig werden alle Konstanten-, Klassen- und Funktionsnamen im globalen Bereich platziert, genau wie vor den von PHP unterstützten Namespaces.
Namespaces werden mit dem Schlüsselwort namespace deklariert. Wenn eine Datei einen Namespace enthält, muss sie den Namespace vor dem gesamten anderen Code deklarieren. Das Syntaxformat ist wie folgt;
<?php // Definiere den Code im Namespace „MyProject“ namespace MyProject;
Sie können auch verschiedene Namespace-Codes in derselben Datei definieren, wie zum Beispiel:
<?php namespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* .. . */ }function connect() { /* ... */ }?>
Es wird nicht empfohlen, diese Syntax zum Definieren mehrerer Namespaces in einer einzelnen Datei zu verwenden. Es wird empfohlen, die folgende Syntax in geschweiften Klammern zu verwenden.
<?phpnamespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* .. . */ } function connect() { /* ... */ }}?>
Um globalen Nicht-Namespace-Code mit Namespace-Code zu kombinieren, kann nur die Syntax mit geschweiften Klammern verwendet werden. Globaler Code muss in eine unbenannte Namespace-Anweisung gefolgt von geschweiften Klammern eingeschlossen werden, zum Beispiel:
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // Globaler Code session_start();$a = MyProject connect();echo MyProjectConnection::start();}?>
Der einzige zulässige Code vor der Deklaration eines Namespace ist die Declare-Anweisung, die die Codierung der Quelldatei definiert. Sämtlicher Nicht-PHP-Code, einschließlich Leerzeichen, darf nicht vor einer Namespace-Deklaration stehen.
<?phpdeclare(encoding='UTF-8'); //Definieren Sie mehrere Namespaces und Code-Namespaces, die nicht im Namespace enthalten sind. MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { / * ... */ }}namespace { // Globaler Code session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
Der folgende Code verursacht einen Syntaxfehler:
<html><?phpnamespace MyProject; // Das Erscheinen von „<html>“ vor dem Namespace führt zu einem schwerwiegenden Fehler – der Namespace muss die erste Anweisung des Programmskripts sein?>
Ähnlich wie die Beziehung zwischen Verzeichnissen und Dateien ermöglichen Ihnen PHP-Namespaces auch die Angabe hierarchischer Namespace-Namen. Daher können Namespace-Namen hierarchisch definiert werden:
<?phpnamespace MyProjectSubLevel; //Deklarieren Sie einen hierarchischen einzelnen Namespace const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
Das obige Beispiel erstellt die Konstante MyProjectSubLevelCONNECT_OK, die Klasse MyProjectSubLevelConnection und die Funktion MyProjectSubLevelConnect.
Klassennamen im PHP-Namespace können auf drei Arten referenziert werden:
Ein unqualifizierter Name oder ein Klassenname ohne Präfix, wie zum Beispiel $a=new foo(); oder foo::staticmethod();. Wenn der aktuelle Namespace currentnamespace ist, wird foo in currentnamespacefoo aufgelöst. Wenn der Code, der foo verwendet, global ist und keinen Code in einem Namespace enthält, wird foo als foo aufgelöst. Warnung: Wenn eine Funktion oder Konstante in einem Namespace undefiniert ist, wird der unqualifizierte Funktions- oder Konstantenname in einen globalen Funktions- oder Konstantennamen aufgelöst.
Ein qualifizierter Name oder ein Name, der ein Präfix enthält, z. B. $a = new subnamespacefoo(); oder subnamespacefoo::staticmethod();. Wenn der aktuelle Namespace currentnamespace ist, wird foo in currentnamespacesubnamespacefoo aufgelöst. Wenn der Code, der foo verwendet, global ist und der Code in keinem Namespace enthalten ist, wird foo in subnamespacefoo aufgelöst.
Ein vollständig qualifizierter Name oder ein Name, der einen globalen Präfixoperator enthält, zum Beispiel $a = new currentnamespacefoo(); oder currentnamespacefoo::staticmethod();. In diesem Fall wird foo im Code immer in den Literalnamen currentnamespacefoo aufgelöst.
Hier ist ein Beispiel für die Verwendung dieser drei Methoden:
Dateicode file1.php
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
Dateicode file2.php
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Unqualifizierter Name*/foo(); // Parsen ist die Funktion FooBarfoofoo::staticmethod(); // Sie wird in die Klasse FooBarfoo geparst und die Methode ist staticmethodecho FOO; Wird in die Konstante FooBarFOO/* qualifizierter Name*/subnamespacefoo() aufgelöst. // Wird in die Funktion FooBarsubnamespacefoo::staticmethod() aufgelöst. // Wird in die Klasse FooBarsubnamespace aufgelöst foo, // und Klassenmethoden staticmethodecho subnamespaceFOO; // analysiert in Konstante FooBarsubnamespaceFOO /* Vollständig qualifizierter Name */FooBarfoo(); // Wird in die Funktion FooBarfooFooBarfoo::staticmethod(); aufgelöst. // Wird in die Klasse FooBarfoo aufgelöst Methode staticmethodecho FooBarFOO; //Aufgelöst als Konstante FooBarFOO?>
Beachten Sie, dass Sie für den Zugriff auf globale Klassen, Funktionen oder Konstanten einen vollständig qualifizierten Namen verwenden können, z. B. strlen() oder Exception oder INI_ALL.
Greifen Sie innerhalb eines Namespace auf globale Klassen, Funktionen und Konstanten zu:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Globale Funktion aufrufen strlen$b = INI_ALL$; c = new Exception('error'); // Instanziieren Sie die globale Klasse Exception?>
Die Implementierung von PHP-Namespaces wird durch die dynamische Natur der Sprache selbst beeinflusst. Wenn Sie also den folgenden Code in einen Namespace umwandeln möchten, greifen Sie dynamisch auf die Elemente zu.
Dateicode example1.php:
<?phpclass classname{ function __construct() { echo __METHOD__,"n";function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // druckt classname::__construct$b = 'funcname';$b(); // druckt funcnameecho konstant('constname'), "n"; // druckt global?>
Sie müssen einen vollständig qualifizierten Namen verwenden (den Klassennamen einschließlich des Namespace-Präfix). Beachten Sie, dass der führende Backslash nicht erforderlich ist, da es in dynamischen Klassennamen, Funktionsnamen oder Konstantennamen keinen Unterschied zwischen qualifizierten und vollständig qualifizierten Namen gibt.
Greifen Sie dynamisch auf Elemente eines Namespace zu
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n";}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'classname';$obj = new $a; // Ausgabe classname::__construct$b = 'funcname';$b(); // Funktionsname ausgeben echo konstant('constname'), "n"; // Ausgabe global/* Wenn doppelte Anführungszeichen verwendet werden, lautet die Verwendungsmethode "\namespacename\classname "* /$a = 'namespacenameclassname';$obj = new $a; // Ausgabe namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // Ausgabenamespacenameclassname::__construct$b = 'namespacenamefuncname';$b(); // Ausgabenamespacenamefuncname$b = 'namespacenamefuncname';$b(); 'namespacenameconstname'), "n" // Ausgabe namespacedecho konstant('namespacenameconstname'), "n"; Ausgabe mit Namensraum?>
PHP unterstützt zwei abstrakte Methoden für den Zugriff auf Elemente innerhalb des aktuellen Namespace: die magische Konstante __NAMESPACE__ und das Schlüsselwort namespace.
Der Wert der Konstante __NAMESPACE__ ist eine Zeichenfolge, die den Namen des aktuellen Namespace enthält. Im globalen Code, der in keinem Namespace enthalten ist, enthält er eine leere Zeichenfolge.
__NAMESPACE__ Beispiel, Code in einem Namespace
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"'; // Ausgabe "MyProject"?>
__NAMESPACE__ Beispiel, globaler Code
<?phpecho '"', __NAMESPACE__, '"'; // Ausgabe ""?>
Die Konstante __NAMESPACE__ ist nützlich, wenn Namen dynamisch erstellt werden, zum Beispiel:
Erstellen Sie Namen dynamisch mit __NAMESPACE__
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ '\' $classname;
Das Schlüsselwort namespace kann verwendet werden, um explizit auf Elemente im aktuellen Namespace oder in Subnamespaces zuzugreifen. Es entspricht dem self-Operator in Klassen.
Namespace-Operator, Code im Namespace
<?phpnamespace MyProject;use blahblah as mine; // siehe „Namespaces verwenden: importing/aliasing“blahmine(); // ruft die Funktion blahblahmine() auf; ruft die Funktion MyProjectblahmine()namespacefunc(); // ruft die Funktion MyProjectfunc()namespacesubfunc() auf MyProjectsubfunc()namespacecname::method(); // ruft die statische Methode „method“ der Klasse MyProjectcname$a auf = neuer Namespacesubcname(); // instanziiert das Objekt der Klasse MyProjectsub cname$b = namespaceCONSTANT; // weist $b?> den Wert der Konstante MyProjectCONSTANT zu
Namespace-Operator, globaler Code
<?phpnamespacefunc(); // ruft die Funktion func()namespacesubfunc(); // ruft die Funktion subfunc()namespacecname::method(); auf class cname$a = new namespacesubcname(); // instanziiert Objekt der Klasse subcname$b = namespaceCONSTANT; // weist $b?> den Wert der Konstante CONSTANT zu
Die PHP-Namespace-Unterstützung bietet zwei Möglichkeiten, Aliase oder Importe zu verwenden: Aliase für Klassennamen oder Aliase für Namespace-Namen.
In PHP wird Aliasing durch den Use-Operator implementiert. Hier ist ein Beispiel mit allen drei möglichen Importmethoden:
1. Verwenden Sie den Use-Operator, um Aliase zu importieren/verwenden
<?phpnamespace foo;use MyFullClassname as Another;// Das folgende Beispiel ist dasselbe wie use MyFullNSname as NSname use MyFullNSname;// Importieren einer globalen Klasse use ArrayObject;$obj = new namespaceAnother; // Instanziiere fooAnother object $obj = new Another; // Instanziiere MyFullClassname object NSnamesubnsfunc(); Rufen Sie die Funktion auf MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Instanziieren Sie das ArrayObject-Objekt // Wenn Sie nicht „use ArrayObject“ verwenden, instanziieren Sie ein fooArrayObject-Objekt? >
2. Eine Zeile enthält mehrere Verwendungsanweisungen
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instanziiere MyFullClassname object NSnamesubnsfunc(); subnsfunc?>
Importvorgänge werden während der Kompilierung ausgeführt, dynamische Klassennamen, Funktionsnamen oder Konstantennamen jedoch nicht.
3. Import und dynamische Namen
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instanziieren eines MyFullClassname-Objekts $a = 'Another';$obj = new $a; ein anderes Objekt?>
Darüber hinaus betrifft der Importvorgang nur unqualifizierte und qualifizierte Namen. Vollqualifizierte Namen sind von Importen nicht betroffen, da sie deterministisch sind.
4. Importieren und vollständig qualifizierte Namen
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instanziiere MyFullClassname class $obj = new Another // Instanziiere eine andere Klasse $obj = new Another thing; // MyFullClassnamething class instanziieren $obj = new Anotherthing; // Anotherthing class instanziieren?>
Wenn PHP innerhalb eines Namespace auf einen nicht qualifizierten Klassen-, Funktions- oder Konstantennamen trifft, verwendet es eine andere Prioritätsstrategie, um den Namen aufzulösen. Klassennamen werden immer in Namen im aktuellen Namespace aufgelöst. Daher müssen Sie beim Zugriff auf Klassennamen, die systemintern sind oder nicht im Namensraum enthalten sind, den vollständig qualifizierten Namen verwenden, zum Beispiel:
1. Greifen Sie auf globale Klassen im Namespace zu
<?phpnamespace ABC;class Exception erweitert Exception {}$a = new Exception('hi'); // $a ist ein Objekt der Klasse ABCException $b = new Exception( 'hi'); // $b ist ein Objekt der Klasse Exception $c = new ArrayObject; // Schwerwiegender Fehler, Klasse ABCArrayObject nicht gefunden?>
Wenn bei Funktionen und Konstanten die Funktion oder Konstante nicht im aktuellen Namensraum vorhanden ist, greift PHP auf die Verwendung der Funktion oder Konstante im globalen Raum zurück.
2. Sichern Sie globale Funktionen/Konstanten im Namespace
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n" // Ausgabe "45"echo INI_ALL, " n"; // Ausgabe „7“ – globale Konstante verwenden INI_ALLecho strlen('hi'), "n"; // Ausgabe "2"if (is_array('hi')) { // Ausgabe „is not array“ echo „is arrayn“;} else { echo „is not arrayn“;}?>
Wenn kein Namespace definiert ist, werden alle Klassen und Funktionen im globalen Raum definiert, genau wie vor der Einführung des Namespace-Konzepts durch PHP. Das Präfix vor einem Namen zeigt an, dass sich der Name im globalen Raum befindet, auch wenn der Name in einem anderen Namensraum liegt.
Verwenden Sie globale Raumanweisungen
<?phpnamespace ABC;/* Diese Funktion ist ABCfopen */function fopen() { /* ... */ $f = fopen(...); // Call global Die fopen-Funktion gibt $f;} ?> zurück
Seit der Einführung von Namespaces ist bei der Verwendung einer Klasse der Suchpfad für diese Klasse am fehleranfälligsten.
<?phpnamespace A;use BD, CE as F;// Funktionsaufruf foo(); // Versuchen Sie zuerst, die im Namespace „A“ definierte Funktion foo() aufzurufen // Versuchen Sie dann, die globale Funktion aufzurufen function" foo"foo(); // Rufen Sie die globale Space-Funktion "foo" auf myfoo(); // Rufen Sie die im Namespace "Amy" definierte Funktion auf F(); Versuchen Sie zuerst, die im Namespace „A“ definierte Funktion „F“ aufzurufen. // Versuchen Sie dann, die globale Funktion „F“ aufzurufen. // Klassenreferenz new B(); // Klasse „B“ erstellen, die im Namespace „A“ definiert ist. Ein Objekt von Klasse „AB“ new D(); // Wenn nicht gefunden, versuchen Sie, die Klasse „AB“ automatisch zu laden. // Erstellen Sie mithilfe von Importregeln ein im Namespace „B“ definiertes Objekt der Klasse „D“. " // Falls nicht gefunden. Wenn gefunden, versuchen Sie, die Klasse „BD“ automatisch neu zu laden F(); // Erstellen Sie mithilfe von Importregeln ein im Namespace „C“ definiertes Objekt der Klasse „E“. // Wenn nicht gefunden, versuchen Sie, die Klasse „CE“ automatisch zu laden. new B(); der im globalen Raum definierten Klasse „B“ // Wenn nicht gefunden, versuchen Sie, die Klasse „B“ automatisch zu laden new D(); // Erstellen Sie ein im globalen Raum definiertes Objekt der Klasse „D“ // Wenn nicht gefunden, versuchen Sie es Autoload-Klasse „D“ neu F(); // Erstelle ein im globalen Raum definiertes Objekt der Klasse „F“ // Wenn nicht gefunden, versuche die Klasse „F“ automatisch zu laden // Rufe eine statische Methode oder Namespace-Funktion in einem anderen Namespace auf Bfoo() ; // Funktion „foo“ im Namespace „AB“ aufrufen B::foo(); // Methode „foo“ der im Namespace „A“ definierten Klasse „B“ aufrufen // Wenn Klasse „AB“ ist nicht gefunden , dann versuchen Sie, die Klasse „AB“ automatisch zu laden. D::foo(); // Verwenden Sie Importregeln, um die im Namespace „B“ definierte Methode „foo“ der Klasse „D“ aufzurufen " " Wenn nicht gefunden, versuchen Sie, die Klasse "BD"Bfoo(); // Funktion "foo" im Namespace "B" aufzurufen. B::foo(); Funktion im globalen Raum Klasse „B“ Die „foo“-Methode // Wenn die Klasse „B“ nicht gefunden wird, versuchen Sie, die Klasse „B“ automatisch zu laden // Eine statische Methode oder Funktion im aktuellen Namespace AB::foo( // Namespace „A“ aufrufen „foo“-Methode der Klasse „B“, definiert in A“ // Wenn die Klasse „AAB“ nicht gefunden wird, versuchen Sie, die Klasse „AAB“AB::foo() automatisch zu laden; // Rufen Sie die „foo“-Methode der Klasse „B“ auf, die im Namespace „A“ definiert ist. // Wenn die Klasse „AB“ nicht gefunden wird, versuchen Sie, die Klasse „AB“ automatisch zu laden?>
Die Namensauflösung folgt den folgenden Regeln:
Aufrufe an vollständig qualifizierte Namen von Funktionen, Klassen und Konstanten werden zur Kompilierungszeit aufgelöst. Beispielsweise wird new AB in die Klasse AB aufgelöst.
Alle unqualifizierten Namen und qualifizierten Namen (nicht vollständig qualifizierte Namen) werden zur Kompilierzeit gemäß den aktuellen Importregeln konvertiert. Wenn beispielsweise der Namespace ABC als C importiert wurde, würden Aufrufe von CDe() in ABCDe() übersetzt.
Innerhalb eines Namespace wird allen qualifizierten Namen, die nicht gemäß Importregeln konvertiert werden, der aktuelle Namespace-Name vorangestellt. Wenn beispielsweise CDe() innerhalb des Namespace AB aufgerufen wird, wird CDe() in ABCDe() konvertiert.
Nicht qualifizierte Klassennamen werden zur Kompilierzeit gemäß den aktuellen Importregeln konvertiert (vollständige Namen werden anstelle von kurzen Importnamen verwendet). Wenn beispielsweise der Namespace ABC als C importiert wird, wird new C() in new ABC() konvertiert.
Innerhalb eines Namensraums (z. B. AB) werden Funktionsaufrufe an unqualifizierte Namen zur Laufzeit aufgelöst. Ein Aufruf der Funktion foo() wird beispielsweise wie folgt geparst:
Suchen Sie im aktuellen Namespace nach einer Funktion mit dem Namen ABfoo()
Versuchen Sie, die Funktion foo() im globalen Raum zu finden und aufzurufen.
Aufrufe an unqualifizierte Namen oder qualifizierte Namensklassen (nicht vollständig qualifizierte Namen) innerhalb eines Namensraums (z. B. AB ) werden zur Laufzeit aufgelöst. Das Folgende ist der Parsing-Prozess zum Aufrufen von new C() und new DE() : Parsing von new C() :
Suchen Sie nach den Klassen ABC im aktuellen Namespace.
Versuchen Sie, die Klassen ABC automatisch zu laden.
Analyse von new DE() :Stellen Sie dem Klassennamen den aktuellen Namespace-Namen voran, sodass ABDE lautet, und suchen Sie dann nach dieser Klasse.
Versuchen Sie, die Klasse ABDE automatisch zu laden.
Um auf eine globale Klasse im globalen Namensraum zu verweisen, muss der vollqualifizierte Name new C() verwendet werden.