English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
PHP namespaces (namespace) are in PHP 5.3added, if you have learned C# and Java, namespaces are not a new thing. However, in PHP, they still have a significant meaning.
PHP namespaces can solve the following two types of problems:
User-written code versus PHP internal classes/Functions/Constants or third-party classes/Functions/Name conflicts between constants
Create an alias (or short) name for a very long identifier name (usually defined to alleviate the first-class problem) to improve the readability of the source code.
By default, all constants, class, and function names are placed in the global space, just as PHP supported namespaces before.
Namespaces are declared using the keyword namespace. If a file contains a namespace, it must be declared before all other code. The syntax format is as follows;
<?php // Define code within the 'MyProject' namespace namespace MyProject; // ... code ...
You can also define different namespace code within the same file, such as:
<?php namespace MyProject; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } namespace AnotherProject; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } ?>
It is not recommended to define multiple namespaces within a single file using this syntax. It is recommended to use the following syntax with curly braces.
<?php namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } ?>
To combine global code outside of a namespace with code within a namespace, the syntax using curly braces must be used. Global code must be enclosed within a namespace statement without a name and curly braces, for example:
<?php namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // Globaler Code session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
Before the declaration of the namespace, the only valid code is the declare statement used to define the encoding of the source file. No non-PHP code, including whitespace, can appear before the declaration of the namespace.
<?php declare(encoding='UTF)-8); //Definition mehrerer Namespaces und Codes, die nicht in Namespaces enthalten sind namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // Globaler Code session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
Der folgende Code führt zu einem Syntaxfehler:
<html> <?php namespace MyProject; // Ein "<html>" vor dem Namespace führt zu einem fatalen Fehler - Der Namespace muss die erste Anweisung im Skript sein ?>
Ähnlich wie das Verhältnis zwischen Verzeichnissen und Dateien, ermöglichen es die Namensräume in PHP, hierarchische Namensräume zu spezifizieren. Daher kann der Name des Namensraums auf hierarchische Weise definiert werden:
<?php namespace MyProject\Sub\Level; //Erklärung eines hierarchischen einzelnen Namensraums const CONNECT_OK = 1; class Connection { /* ... */ } function Connect() { /* ... */ } ?>
Der obige Beispielcode erstellt die Konstante MyProject\Sub\Level\CONNECT_OK, die Klasse MyProject\Sub\Level\Connection und die Funktion MyProject\Sub\Level\Connect.
Der Klassename in einem PHP-Namespace kann auf drei Arten referenziert werden:
Nicht eingeschränkter Name, oder Name der Klasse ohne Präfix.Zum Beispiel $a = new foo(); oder foo::staticmethod();. Wenn der aktuelle Namespace currentnamespace ist, wird foo als currentnamespace\foo interpretiert. Wenn der Code, der foo verwendet, global ist und nicht in einem Namespace enthalten ist, wird foo als foo interpretiert. Warnung: Wenn eine Funktion oder eine Konstante im Namespace nicht definiert ist, wird der nicht eingeschränkte Funktionsname oder der Name der Konstante als globaler Funktionsname oder globaler Konstantenname interpretiert.
Bezeichner, oder Namen mit Präfix.Zum Beispiel $a = new subnamespace\foo(); oder subnamespace\foo::staticmethod();. Wenn der aktuelle Namespace currentnamespace ist, wird foo als currentnamespace\subnamespace\foo interpretiert. Wenn der Code, der foo verwendet, global ist und nicht in einem Namespace enthalten ist, wird foo als subnamespace\foo interpretiert.
Vollständiger Name oder Namen, die den Globalen Präfix-Operator enthalten.Zum Beispiel, $a = new \currentnamespace\foo(); oder \currentnamespace\foo::staticmethod();. In diesem Fall wird foo immer als der im Code verwendete Textname (literal name) currentnamespace\foo ge解析ert.
Nachfolgend ist ein Beispiel für die Verwendung dieser drei Methoden:
file1.php-Datei-Code
<?php namespace Foo\Bar\subnamespace; const FOO = 1; function foo() {} class foo { static function staticmethod() {} } ?>
file2.php-Datei-Code
<?php namespace Foo\Bar; include 'file1.php'; const FOO = 2; function foo() {} class foo { static function staticmethod() {} } /* Nichtqualifizierter Name */ foo(); // wird in die Funktion Foo\Bar\foo ge解析ert foo::staticmethod(); // wird in die Klasse Foo\Bar\foo ,Methode staticmethod ge解析ert echo FOO; // wird in die Konstante Foo\Bar\FOO ge解析ert /* Bezeichner */ subnamespace\foo(); // wird in die Funktion Foo\Bar\subnamespace\foo ge解析ert subnamespace\foo::staticmethod(); // wird in die Klasse Foo\Bar\subnamespace\foo, ge解析ert // sowie in die Methoden der Klasse staticmethod echo subnamespace\FOO; // wird in die Konstante Foo\Bar\subnamespace\FOO ge解析ert /* Vollständiger Name */ \Foo\Bar\foo(); // wird in die Funktion Foo\Bar\foo ge解析ert \Foo\Bar\foo::staticmethod(); // wird in die Klasse Foo\Bar\foo, sowie in die Methoden der Klasse ge解析ert staticmethod echo \Foo\Bar\FOO; // wird in die Konstante Foo\Bar\FOO ge解析ert ?>
Beachten Sie, dass der Zugriff auf beliebige globale Klassen, Funktionen oder Konstanten mit dem vollständigen Namen erfolgen kann, z.B. \strlen() oder \Exception oder \INI_ALL.
Zugriff auf globale Klassen, Funktionen und Konstanten innerhalb des Namensraums:
<?php namespace Foo; function strlen() {} const INI_ALL = ; 3; class Exception {} $a = \strlen('hi'); // Aufruf der globalen Funktion strlen $b = \INI_ALL; // Zugriff auf die globale Konstante INI_ALL $c = new \Exception('error'); // Beispielhafter Aufruf der globalen Klasse Exception ?>
Die Implementierung von PHP-Namensräumen wird durch die dynamischen Eigenschaften der Sprache selbst beeinflusst. Daher muss, wenn der folgende Code in einen Namensraum überführt wird, auf dynamische Elemente zugegriffen werden.
example1.php Datei-Code:
<?php class classname { function __construct() { echo __METHOD__, '\n'; } } function funcname() { echo __FUNCTION__, '\n'; } const constname = 'global'; $a = 'classname'; $obj = new $a; // prints classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), '\n'; // prints global ?>
Es muss der vollständige Name verwendet werden (einschließlich des Namensraums vor dem Klassennamen). Beachten Sie, dass der führende Backslash in dynamischen Klassennamen, Funktionsnamen oder Konstantennamen nicht erforderlich ist, da es zwischen dem eingeschränkten und dem vollständigen Namen keinen Unterschied gibt.
Dynamischer Zugriff auf die Elemente des Namensraums
<?php namespace 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(); // Ausgabe des Funktionsnamens echo constant('constname'), '\n'; // Ausgabe global /* Verwenden Sie Anführungszeichen, um den folgenden Stil zu verwenden: \\\'namespacename\\classname\\'*/ $a = '\namespacename\classname'; $obj = new $a; // Ausgabe namespacename\classname::__construct $a = 'namespacename\classname'; $obj = new $a; // Ausgabe namespacename\classname::__construct $b = 'namespacename\funcname'; $b(); // output namespacename\funcname $b = 'namespacename\funcname'; $b(); // output namespacename\funcname echo constant('\namespacename\constname'), '\n'; // output namespaced echo constant('namespacename\constname'), '\n'; // output namespaced ?>
PHP supports two methods for abstractly accessing elements within the current namespace, the __NAMESPACE__ magic constant and the namespace keyword.
The value of the constant __NAMESPACE__ is a string containing the name of the current namespace. In global code, which is not included in any namespace, it contains an empty string.
__NAMESPACE__ example, code within a namespace
<?php namespace MyProject; echo '"', __NAMESPACE__, '"'; // output "MyProject" ?>
__NAMESPACE__ example, global code
<?php echo '"', __NAMESPACE__, '"'; // output "" ?>
The constant __NAMESPACE__ is very useful when dynamically creating names, for example:
Using __NAMESPACE__ to dynamically create names
<?php namespace MyProject; function get($classname) { $a = __NAMESPACE__ . '\\' . $classname; return new $a; } ?>
The keyword namespace can be used to explicitly access elements in the current namespace or subnamespace. It is equivalent to the self operator within a class.
namespace operator, code within a namespace
<?php namespace MyProject; use blah\blah as mine; // see "Using namespaces: importing/aliasing" blah\mine(); // calls function blah\blah\mine() namespace\blah\mine(); // calls function MyProject\blah\mine() namespace\func(); // calls function MyProject\func() namespace\sub\func(); // calls function MyProject\sub\func() namespace\cname::method(); // calls static method "method" of class MyProject\cname $a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname $b = namespace\CONSTANT; // zuweist den Wert der Konstante MyProject\CONSTANT zu $b ?>
Namespace-Operator, globaler Code
<?php namespace\func(); // ruft die Funktion func() auf namespace\sub\func(); // ruft die Funktion sub\func() auf namespace\cname::method(); // ruft die statische Methode "method" der Klasse cname auf $a = new namespace\sub\cname(); // instanziert ein Objekt der Klasse sub\cname $b = namespace\CONSTANT; // zuweist den Wert der Konstante CONSTANT zu $b ?>
PHP unterstützt zwei Arten der Verwendung von Aliases oder Importen: das Benennen von Klassennamen oder Namensräumen als Alias.
In PHP wird das Alias durch den Operator use realisiert. Hier ist ein Beispiel für alle drei möglichen Arten von Importen:
1、 Verwendung des use-Operators zum Import/Verwendung von Aliases
<?php namespace foo; use My\Full\Classname as Another; // Der folgende Beispiel ist gleichwertig mit "use My\Full\NSname as NSname" use My\Full\NSname; // Import einer globalen Klasse use \ArrayObject; $obj = new namespace\Another; // Demonstration eines "foo\Another"-Objekts $obj = new Another; // Demonstration eines Objekts von "My\Full\Classname" NSname\subns\func(); // Aufruf der Funktion "My\Full\NSname\subns\func" $a = new ArrayObject(array(1)); // Demonstration eines "ArrayObject"-Objekts // Ohne "use \ArrayObject" zu verwenden, wird ein Objekt "foo\ArrayObject" demonstriert ?>
2、 mehrerer use-Anweisungen in einer Zeile
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // Demonstration eines Objekts von "My\Full\Classname" NSname\subns\func(); // Aufruf der Funktion "My\Full\NSname\subns\func" ?>
Import-Operationen werden bei der Kompilierung ausgeführt, aber dynamische Klassennamen, Funktionsnamen oder Konstantennamen nicht.
3Import und dynamische Namen
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // Demonstration eines Objekts von "My\Full\Classname" $a = 'Another'; $obj = new $a; // Actualisierung eines Another-Objekts ?>
Darüber hinaus betrifft der Import nur nicht qualifizierte und qualifizierte Namen. Voll qualifizierte Namen sind bestimmt und daher nicht vom Import betroffen.
4、Import und voll qualifizierte Namen
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // Demonstration der Klasse My\Full\Classname $obj = new \Another; // Demonstration der Klasse Another $obj = new Another\thing; // Demonstration der Klasse My\Full\Classname\thing $obj = new \Another\thing; // Demonstration der Klasse Another\thing ?>
In einem Namespace verwendet PHP eine andere Prioritätsstrategie, um einen nicht qualifizierten Klassennamen, eine Funktion oder eine Konstante zu解析. Der Klassename wird immer auf den Namen im aktuellen Namespace gelöst. Daher muss der voll qualifizierte Name verwendet werden, wenn auf Systeminterne oder nicht im Namespace enthaltenen Klassennamen zugegriffen wird, z.B.:
1、Zugriff auf globale Klassen im Namespace
<?php namespace A\B\C; class Exception extends \Exception {} $a = new Exception('hi'); // $a ist ein Objekt der Klasse A\B\C\Exception $b = new \Exception('hi'); // $b ist ein Objekt der Klasse Exception $c = new ArrayObject; // Schwerer Fehler, die Klasse A\B\C\ArrayObject kann nicht gefunden werden ?>
Für Funktionen und Konstanten verwendet PHP, wenn die Funktion oder die Konstante im aktuellen Namespace nicht existiert, die Funktionen oder Konstanten im globalen Raum.
2、Ersatz globale Funktionen im Namespace/Konstanten
<?php namespace A\B\C; const E_ERROR = 45; function strlen($str) { return \strlen($str) - 1; } echo E_ERROR, "\n"; // Ausgabe ""45" echo INI_ALL, "\n"; // Ausgabe ""7" - Verwenden Sie den globalen Konstanten INI_ALL echo strlen('hi'), "\n"; // Ausgabe ""1" if (is_array('hi')) { // Ausgabe "is not array" echo "is array\n"; } else { echo "is not array\n"; } ?>
If no namespace is defined, all class and function definitions are in the global space, just like before the introduction of the namespace concept in PHP. Prefixing the name with \ indicates that the name is in the global space, even if the name is located in another namespace.
Use global space specification
<?php namespace A\B\C; /* This function is A\B\C\fopen */ function fopen() { /* ... */ $f = \fopen(...); // Call the global fopen function return $f; } ?>
Since the introduction of namespaces, the most easily made mistake should be when using a class, what is the search path for this class.
<?php namespace A; use B\D, C\E as F; // Function call foo(); // Firstly, try to call the function foo() defined in the namespace "A" // Try to call the global function "foo" again \foo(); // Call the global function "foo" my\foo(); // Call the function "foo" defined in the namespace "A\my" F(); // Firstly, try to call the function "F" defined in the namespace "A" // Try to call the global function "F" again // Class reference new B(); // Create an object of the class "B" defined in the namespace "A" // If not found, try to automatically load the class "A\B" new D(); // Using import rules, create an object of the class "D" defined in the namespace "B" // If not found, try to automatically load the class "B\D" new F(); // Using import rules, create an object of the class "E" defined in the namespace "C" // If not found, try to automatically load the class "C\E" new \B(); // Create an object of the class "B" defined in the global space // If not found, try to automatically load the class "B" new \D(); // Create an object of the class "D" defined in the global space // If not found, try to automatically load the class "D" new \F(); // Create an object of the class "F" defined in the global space // If not found, try to automatically load the class "F" // Call a static method or namespace function in another namespace B\foo(); // Call the function "foo" in the namespace "A\B" B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法 // If the class "A\B" is not found, try to automatically load the class "A\B" D::foo(); // Using import rules, call the "foo" method of the class "D" defined in the namespace "B" // 如果类 "B\D" 未找到,则尝试自动加载类 "B\D" \B\foo(); // 调用命名空间 "B" 中的函数 "foo" \B::foo(); // 调用全局空间中的类 "B" 的 "foo" 方法 // 如果类 "B" 未找到,则尝试自动加载类 "B" // 当前命名空间中的静态方法或函数 A\B::foo(); // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法 // 如果类 "A\A\B" 未找到,则尝试自动加载类 "A\A\B" \A\B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法 // 如果类 "A\B" 未找到,则尝试自动加载类 "A\B" ?>
名称解析遵循下列规则:
对完全限定名称的函数,类和常量的调用在编译时解析。例如 new \A\B 解析为类 A\B。
所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 A\B\C 被导入为 C,那么对 C\D\e() 的调用就会被转换为 A\B\C\D\e()。
在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 A\B 内部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e() 。
非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为C,则 new C() 被转换为 new A\B\C() 。
在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:
在当前命名空间中查找名为 A\B\foo() 的函数
尝试查找并调用 全局(global) 空间中的函数 foo()。
在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用 new C() 及 new D\E() 的解析过程: new C()的解析: new D\E()的解析:为了引用全局命名空间中的全局类,必须使用完全限定名称 new \C()。
在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。
尝试自动加载类 A\B\D\E。
在当前命名空间中查找A\B\C类。
尝试自动加载类A\B\C。