PHP namespace
PHP namespace (namespace)
PHP namespace (namespace) was added in PHP 5.3. If you have studied C# and Java, then namespace is nothing new. However, it still has a very important significance in PHP.
PHP namespace can solve the following two types of problems:
1. Name conflicts between user-written code and PHP internal classes/functions/constants or third-party classes/functions/constants .
2. Create an alias (or short) name for a very long identifier name (usually defined to alleviate the first type of problem) to improve the readability of the source code.
Define namespace
By default, all constants, classes and function names are placed in the global space, just like PHP supports naming Space is the same as before.
The namespace is declared through the keyword namespace. If a file contains a namespace, it must declare the namespace before all other code. The syntax format is as follows;
< ?php // 定義代碼在 'MyProject' 命名空間中 namespace MyProject; // ... 代碼 ...
You can also define different namespace codes in the same file, such as:
< ?php namespace MyProject1; // MyProject1 命名空間中的PHP代碼 namespace MyProject2; // MyProject2 命名空間中的PHP代碼 // 另一種語法 namespace MyProject3 { // MyProject3 命名空間中的PHP代碼 } ?>
The only legal code before declaring a namespace is the one used to define the source file Encoding declare statement. All non-PHP code, including whitespace, must not appear before a namespace declaration.
<?php declare(encoding='UTF-8'); //定義多個命名空間和不包含在命名空間中的代碼 namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // 全局代碼 session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
The following code will cause a syntax error:
<html> <?php namespace MyProject; // 命名空間前出現(xiàn)了“<html>” 會致命錯誤 - 命名空間必須是程序腳本的第一條語句 ?>
Subnamespace
with directory Much like files, PHP namespaces also allow you to specify hierarchical namespace names. Therefore, namespace names can be defined in a hierarchical manner:
<?php namespace MyProject\Sub\Level; //聲明分層次的單個命名空間 const CONNECT_OK = 1; class Connection { /* ... */ } function Connect() { /* ... */ } ?>
The above example creates the constant MyProject\Sub\Level\CONNECT_OK, the class MyProject\Sub\Level\Connection and the function MyProject\Sub\Level \Connect.
#Namespace usage
Class names in the PHP namespace can be referenced in three ways: 1. Unqualified names, or class names that do not include a prefix, such as $a=new foo(); or foo: :staticmethod();. If the current namespace is currentnamespace, foo will be resolved to currentnamespace\foo. If the code using foo is global and does not contain code in any namespace, foo will be resolved as foo. Warning: If a function or constant in the namespace is undefined, the unqualified function or constant name is resolved to a global function or constant name. 2. Qualified name, or name containing prefix, such as $a = new subnamespace\foo(); or subnamespace\foo::staticmethod();. If the current namespace is currentnamespace, foo will be resolved to currentnamespace\subnamespace\foo. If the code using foo is global, code not contained in any namespace, foo will be resolved to subnamespace\foo.3. Fully qualified name, or a name that includes a global prefix operator, for example, $a = new \currentnamespace\foo(); or \currentnamespace\foo::staticmethod();. In this case, foo is always resolved to the literal name currentnamespace\foo in the code.
The following is an example of using these three methods:
file1.php file code
<?php namespace Foo\Bar\subnamespace; const FOO = 1; function foo() {} class foo { static function staticmethod() {} } ?>
file2.php file code
<?php namespace Foo\Bar; include 'file1.php'; const FOO = 2; function foo() {} class foo { static function staticmethod() {} } /* 非限定名稱 */ foo(); // 解析為 Foo\Bar\foo resolves to function Foo\Bar\foo foo::staticmethod(); // 解析為類 Foo\Bar\foo的靜態(tài)方法staticmethod。resolves to class Foo\Bar\foo, method staticmethod echo FOO; // resolves to constant Foo\Bar\FOO /* 限定名稱 */ subnamespace\foo(); // 解析為函數(shù) Foo\Bar\subnamespace\foo subnamespace\foo::staticmethod(); // 解析為類 Foo\Bar\subnamespace\foo, // 以及類的方法 staticmethod echo subnamespace\FOO; // 解析為常量 Foo\Bar\subnamespace\FOO /* 完全限定名稱 */ \Foo\Bar\foo(); // 解析為函數(shù) Foo\Bar\foo \Foo\Bar\foo::staticmethod(); // 解析為類 Foo\Bar\foo, 以及類的方法 staticmethod echo \Foo\Bar\FOO; // 解析為常量 Foo\Bar\FOO ?>
Note that to access any global class, function or constant, you can use a fully qualified name, such as \strlen() or \Exception or \INI_ALL.
Accessing global classes, functions and constants inside a namespace:
<?php namespace Foo; function strlen() {} const INI_ALL = 3; class Exception {} $a = \strlen('hi'); // 調(diào)用全局函數(shù)strlen $b = \INI_ALL; // 訪問全局常量 INI_ALL $c = new \Exception('error'); // 實例化全局類 Exception ?>
##Namespaces and dynamic language features
The implementation of PHP namespaces is affected by the dynamic characteristics of the language itself. So if you want to convert the code below into a namespace, access the elements dynamically. example1.php file 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 ?>Must use a fully qualified name (class name including namespace prefix). Note that the leading backslash is unnecessary because there is no difference between qualified and fully qualified names in dynamic class names, function names, or constant names.
Dynamic access to namespace elements
<?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; // prints classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "\n"; // prints global /* note that if using double quotes, "\namespacename\classname" must be used */ $a = '\namespacename\classname'; $obj = new $a; // prints namespacename\classname::__construct $a = 'namespacename\classname'; $obj = new $a; // also prints namespacename\classname::__construct $b = 'namespacename\funcname'; $b(); // prints namespacename\funcname $b = '\namespacename\funcname'; $b(); // also prints namespacename\funcname echo constant('\namespacename\constname'), "\n"; // prints namespaced echo constant('namespacename\constname'), "\n"; // also prints namespaced ?>
namespace keyword and __NAMESPACE__ Constants
PHP supports two abstract methods of 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, not included in any namespace, it contains an empty string. __NAMESPACE__ example, code in a namespace<?php namespace MyProject; echo '"', __NAMESPACE__, '"'; // 輸出 "MyProject" ?>__NAMESPACE__ example, global code
<?php echo '"', __NAMESPACE__, '"'; // 輸出 "" ?>The constant __NAMESPACE__ is useful when creating names dynamically, for example:
Use __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 sub-namespaces. It is equivalent to the self operator in classes. namespace operator, code in the 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; // assigns value of constant MyProject\CONSTANT to $b ?>namespace operator, global code
<?php namespace\func(); // calls function func() namespace\sub\func(); // calls function sub\func() namespace\cname::method(); // calls static method "method" of class cname $a = new namespace\sub\cname(); // instantiates object of class sub\cname $b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b ?>
Use namespace :Alias/Import
PHP namespace support has two ways of using aliases or imports: using aliases for class names, or using aliases for namespace names. Note that PHP does not support imported functions or constants. In PHP, aliases are implemented through the operator use. The following is an example of using all three possible import methods: 1. Use the use operator to import/use aliases<?php namespace foo; use My\Full\Classname as Another; // 下面的例子與 use My\Full\NSname as NSname 相同 use My\Full\NSname; // 導入一個全局類 use \ArrayObject; $obj = new namespace\Another; // 實例化 foo\Another 對象 $obj = new Another; // 實例化 My\Full\Classname 對象 NSname\subns\func(); // 調(diào)用函數(shù) My\Full\NSname\subns\func $a = new ArrayObject(array(1)); // 實例化 ArrayObject 對象 // 如果不使用 "use \ArrayObject" ,則實例化一個 foo\ArrayObject 對象 ?>2. One line contains multiple use statements
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 實例化 My\Full\Classname 對象 NSname\subns\func(); // 調(diào)用函數(shù) My\Full\NSname\subns\func ?>The import operation is executed during compilation, but the dynamic class name, function name or constant name is not. 3. Import and dynamic names
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 實例化一個 My\Full\Classname 對象 $a = 'Another'; $obj = new $a; // 實際化一個 Another 對象 ?>In addition, the import operation only affects unqualified names and qualified names. Fully qualified names are not affected by imports because they are deterministic. 4, Import and fully qualified name
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // instantiates object of class My\Full\Classname $obj = new \Another; // instantiates object of class Another $obj = new Another\thing; // instantiates object of class My\Full\Classname\thing $obj = new \Another\thing; // instantiates object of class Another\thing ?>
Using namespaces: fallback global functions/constants
In a namespace, when PHP encounters an unqualified class, function, or constant name, it uses a different priority strategy to resolve the name. Class names always resolve to names in the current namespace. Therefore, when accessing class names inside the system or not included in the namespace, you must use fully qualified names, for example:
1. Access global classes in the namespace
<?php namespace A\B\C; class Exception extends \Exception {} $a = new Exception('hi'); // $a 是類 A\B\C\Exception 的一個對象 $b = new \Exception('hi'); // $b 是類 Exception 的一個對象 $c = new ArrayObject; // 致命錯誤, 找不到 A\B\C\ArrayObject 類 ?>
For functions and For constants, if the function or constant does not exist in the current namespace, PHP will fall back to using the function or constant in the global space.
2. Backup global functions/constants in the namespace
<?php namespace A\B\C; const E_ERROR = 45; function strlen($str) { return \strlen($str) - 1; } echo E_ERROR, "\n"; // 輸出 "45" echo INI_ALL, "\n"; // 輸出 "7" - 使用全局常量 INI_ALL echo strlen('hi'), "\n"; // 輸出 "1" if (is_array('hi')) { // 輸出 "is not array" echo "is array\n"; } else { echo "is not array\n"; } ?>
##Global space
If no namespace is defined, all classes and functions are defined in the global space, just like before PHP introduced the namespace concept. Prefixing a name with \ indicates that the name is in the global space, even if the name is in another namespace. Instructions for using global space<?php namespace A\B\C; /* 這個函數(shù)是 A\B\C\fopen */ function fopen() { /* ... */ $f = \fopen(...); // 調(diào)用全局的fopen函數(shù) return $f; } ?>
The order of namespaces
Since there is a namespace After that, the most error-prone thing is when using a class, what is the search path for this class.<?php namespace A; use B\D, C\E as F; // 函數(shù)調(diào)用 foo(); // 首先嘗試調(diào)用定義在命名空間"A"中的函數(shù)foo() // 再嘗試調(diào)用全局函數(shù) "foo" \foo(); // 調(diào)用全局空間函數(shù) "foo" my\foo(); // 調(diào)用定義在命名空間"A\my"中函數(shù) "foo" F(); // 首先嘗試調(diào)用定義在命名空間"A"中的函數(shù) "F" // 再嘗試調(diào)用全局函數(shù) "F" // 類引用 new B(); // 創(chuàng)建命名空間 "A" 中定義的類 "B" 的一個對象 // 如果未找到,則嘗試自動裝載類 "A\B" new D(); // 使用導入規(guī)則,創(chuàng)建命名空間 "B" 中定義的類 "D" 的一個對象 // 如果未找到,則嘗試自動裝載類 "B\D" new F(); // 使用導入規(guī)則,創(chuàng)建命名空間 "C" 中定義的類 "E" 的一個對象 // 如果未找到,則嘗試自動裝載類 "C\E" new \B(); // 創(chuàng)建定義在全局空間中的類 "B" 的一個對象 // 如果未發(fā)現(xiàn),則嘗試自動裝載類 "B" new \D(); // 創(chuàng)建定義在全局空間中的類 "D" 的一個對象 // 如果未發(fā)現(xiàn),則嘗試自動裝載類 "D" new \F(); // 創(chuàng)建定義在全局空間中的類 "F" 的一個對象 // 如果未發(fā)現(xiàn),則嘗試自動裝載類 "F" // 調(diào)用另一個命名空間中的靜態(tài)方法或命名空間函數(shù) B\foo(); // 調(diào)用命名空間 "A\B" 中函數(shù) "foo" B::foo(); // 調(diào)用命名空間 "A" 中定義的類 "B" 的 "foo" 方法 // 如果未找到類 "A\B" ,則嘗試自動裝載類 "A\B" D::foo(); // 使用導入規(guī)則,調(diào)用命名空間 "B" 中定義的類 "D" 的 "foo" 方法 // 如果類 "B\D" 未找到,則嘗試自動裝載類 "B\D" \B\foo(); // 調(diào)用命名空間 "B" 中的函數(shù) "foo" \B::foo(); // 調(diào)用全局空間中的類 "B" 的 "foo" 方法 // 如果類 "B" 未找到,則嘗試自動裝載類 "B" // 當前命名空間中的靜態(tài)方法或函數(shù) A\B::foo(); // 調(diào)用命名空間 "A\A" 中定義的類 "B" 的 "foo" 方法 // 如果類 "A\A\B" 未找到,則嘗試自動裝載類 "A\A\B" \A\B::foo(); // 調(diào)用命名空間 "A\B" 中定義的類 "B" 的 "foo" 方法 // 如果類 "A\B" 未找到,則嘗試自動裝載類 "A\B" ?>Name resolution follows the following rules: 1. Calls to functions, classes, and constants with fully qualified names are resolved at compile time. For example new \A\B resolves to class A\B. 2. All unqualified names and qualified names (non-fully qualified names) are converted at compile time according to the current import rules. For example, if namespace A\B\C is imported as C, then calls to C\D\e() will be translated to A\B\C\D\e(). 3. Within the namespace, all qualified names that are not converted according to import rules will have the current namespace name in front of them. For example, if C\D\e() is called within namespace A\B, C\D\e() will be converted to A\B\C\D\e(). 4. Unqualified class names are converted at compile time according to the current import rules (full names are used instead of short import names). For example, if namespace A\B\C is imported as C, then new C() is converted to new A\B\C() . 5. Within a namespace (e.g. A\B), function calls to unqualified names are resolved at runtime. For example, the call to function foo() is parsed like this: 1. Find the function named A\B\foo() in the current namespace 2. Try to find and call Function foo() in global space. 6. Calls to unqualified names or qualified name classes (non-fully qualified names) within a namespace (e.g. A\B) are resolved at runtime. The following is the parsing process of calling new C() and new D\E(): Parsing of new C():
1. Find classes A\B\C in the current namespace.
2. Try to automatically load class A\B\C.
Parsing of new D\E():
3. Add the current namespace name in front of the class name to become: A\B\D\E, and then search for the class.
4. Try to automatically load class A\B\D\E.
In order to reference a global class in the global namespace, the fully qualified name new \C() must be used.