PHP namespace (namespace) was added in PHP 5.3. If you have studied C# and Java, namespace is nothing new. However, it still has a very important significance in PHP.
PHP namespaces can solve the following two types of problems:
Name conflicts between user-written code and PHP internal classes/functions/constants or third-party classes/functions/constants.
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.
By default, all constant, class, and function names are placed in the global space, just like before PHP supported namespaces.
Namespaces are declared using 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 // Define the code in the 'MyProject' namespace namespace MyProject; // ... code...
You can also define different namespace codes in 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 use this syntax to define multiple namespaces in a single file. It is recommended to use the following curly bracket form of syntax.
<?phpnamespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* .. . */ } function connect() { /* ... */ }}?>
To combine global non-namespace code with namespace code, only curly bracket syntax can be used. Global code must be enclosed in an unnamed namespace statement followed by braces, for example:
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // Global code session_start();$a = MyProject connect();echo MyProjectConnection::start();}?>
The only legal code before declaring a namespace is the declare statement that defines the encoding of the source file. All non-PHP code, including whitespace, cannot appear before a namespace declaration.
<?phpdeclare(encoding='UTF-8'); //Define multiple namespaces and code namespaces not included in the namespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { /* ... */ }}namespace { // Global code session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
The following code will cause a syntax error:
<html><?phpnamespace MyProject; // "<html>" appearing before the namespace will cause a fatal error - the namespace must be the first statement of the program script?>
Much like the relationship between directories and files, PHP namespaces also allow you to specify hierarchical namespace names. Therefore, namespace names can be defined in a hierarchical manner:
<?phpnamespace MyProjectSubLevel; //Declare a hierarchical single namespace const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
The above example creates the constant MyProjectSubLevelCONNECT_OK, the class MyProjectSubLevelConnection and the function MyProjectSubLevelConnect.
Class names in the PHP namespace can be referenced in three ways:
An unqualified name, or a class name without a prefix, such as $a=new foo(); or foo::staticmethod();. If the current namespace is currentnamespace, foo will be resolved to currentnamespacefoo. If the code using foo is global and does not contain code in any namespace, then foo will be resolved as foo. Warning: If a function or constant in a namespace is undefined, the unqualified function or constant name is resolved to a global function or constant name.
A qualified name, or a name that includes a prefix, such as $a = new subnamespacefoo(); or subnamespacefoo::staticmethod();. If the current namespace is currentnamespace, foo will be resolved to currentnamespacesubnamespacefoo. If the code using foo is global, code not contained in any namespace, foo will be resolved to subnamespacefoo.
A fully qualified name, or a name that includes a global prefix operator, for example, $a = new currentnamespacefoo(); or currentnamespacefoo::staticmethod();. In this case, foo is always resolved to the literal name currentnamespacefoo in the code.
Here is an example of using these three methods:
file1.php file code
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
file2.php file code
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Unqualified name*/foo(); // Parsing It is the function FooBarfoofoo::staticmethod(); // It is parsed into the class FooBarfoo and the method is staticmethodecho FOO; // Resolves to constant FooBarFOO/* qualified name*/subnamespacefoo(); // Resolves to function FooBarsubnamespacefoosubnamespacefoo::staticmethod(); // Resolves to class FooBarsubnamespace foo, // and class methods staticmethodecho subnamespaceFOO; // parsed to constant FooBarsubnamespaceFOO /* Fully qualified name */FooBarfoo(); // Resolves to function FooBarfooFooBarfoo::staticmethod(); // Resolves to class FooBarfoo, and the class's Method staticmethodecho FooBarFOO; //Resolved as constant FooBarFOO?>
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.
Access global classes, functions and constants within a namespace:
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // Call global function strlen$b = INI_ALL; // Access global constant INI_ALL$ c = new Exception('error'); // Instantiate the global class Exception?>
The implementation of PHP namespaces is affected by the dynamic nature of the language itself. So if you want to convert the code below into a namespace, access the elements dynamically.
example1.php file code:
<?phpclass 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 funcnameecho constant('constname'), "n"; // prints global?>
You must use a fully qualified name (the class name including the 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.
Dynamically access elements of a namespace
<?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; // Output classname::__construct$b = 'funcname';$b(); // Output function name echo constant('constname'), "n"; // Output global/* If double quotes are used, the usage method is "\namespacename\classname"* /$a = 'namespacenameclassname';$obj = new $a; // Output namespacenameclassname::__construct$a = 'namespacenameclassname';$obj = new $a; // Output namespacenameclassname::__construct$b = 'namespacenamefuncname';$b(); // Output namespacenamefuncname$b = 'namespacenamefuncname';$b(); // Output namespacenamefuncnameecho constant( 'namespacenameconstname'), "n"; // Output namespacedecho constant('namespacenameconstname'), "n"; // Output namespaced?>
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
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"'; // Output "MyProject"?>
__NAMESPACE__ example, global code
<?phpecho '"', __NAMESPACE__, '"'; // Output ""?>
The constant __NAMESPACE__ is useful when creating names dynamically, for example:
Create names dynamically using __NAMESPACE__
<?phpnamespace 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 subnamespaces. It is equivalent to the self operator in classes.
namespace operator, code in the namespace
<?phpnamespace MyProject;use blahblah as mine; // see "Using namespaces: importing/aliasing"blahmine(); // calls function blahblahmine()namespaceblahmine(); // calls function MyProjectblahmine()namespacefunc(); // calls function MyProjectfunc()namespacesubfunc(); // calls function MyProjectsubfunc()namespacecname::method(); // calls static method "method" of class MyProjectcname$a = new namespacesubcname(); // instantiates object of class MyProjectsub cname$b = namespaceCONSTANT; // assigns value of constant MyProjectCONSTANT to $b?>
namespace operator, global code
<?phpnamespacefunc(); // calls function func()namespacesubfunc(); // calls function subfunc()namespacecname::method(); // calls static method "method" of class cname$a = new namespacesubcname(); // instantiates object of class subcname$b = namespaceCONSTANT; // assigns value of constant CONSTANT to $b?>
PHP namespace support has two ways of using aliases or imports: using aliases for class names, or using aliases for namespace names.
In PHP, aliasing is implemented through the use operator. Here is an example using all three possible import methods:
1. Use the use operator to import/use aliases
<?phpnamespace foo;use MyFullClassname as Another;// The following example is the same as use MyFullNSname as NSname use MyFullNSname;// Import a global class use ArrayObject;$obj = new namespaceAnother; // Instantiate fooAnother object $obj = new Another; // Instantiate MyFullClassname object NSnamesubnsfunc(); // Call the function MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // Instantiate the ArrayObject object // If you do not use "use ArrayObject", instantiate a fooArrayObject object?>
2. One line contains multiple use statements
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instantiate MyFullClassname object NSnamesubnsfunc(); // Call function MyFullNSname subnsfunc?>
Import operations are performed during compilation, but dynamic class names, function names, or constant names are not.
3. Import and dynamic names
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instantiate a MyFullClassname object $a = 'Another';$obj = new $a; // Actualize an Another object?>
Additionally, the import operation affects only unqualified and qualified names. Fully qualified names are not affected by imports because they are deterministic.
4. Import and fully qualified names
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // Instantiate MyFullClassname class $obj = new Another; // Instantiate Another class $obj = new Anotherthing; // Instantiate MyFullClassnamething class $obj = new Anotherthing; // Instantiate Anotherthing class?>
Within a namespace, when PHP encounters an unqualified class, function, or constant name, it uses a different precedence strategy to resolve the name. Class names always resolve to names in the current namespace. Therefore when accessing class names that are internal to the system or not contained in the namespace, you must use the fully qualified name, for example:
1. Access global classes in the namespace
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a is an object of class ABCException $b = new Exception( 'hi'); // $b is an object of class Exception $c = new ArrayObject; // Fatal error, class ABCArrayObject not found?>
For functions and 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
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n"; // Output "45"echo INI_ALL, " n"; // Output "7" - use global constant INI_ALLecho strlen('hi'), "n"; // Output "2"if (is_array('hi')) { // Output "is not array" echo "is arrayn";} else { echo "is not arrayn";}?>
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.
Use global space instructions
<?phpnamespace ABC;/* This function is ABCfopen */function fopen() { /* ... */ $f = fopen(...); // Call global The fopen function returns $f;} ?>
Since the introduction of namespaces, the most error-prone thing is when using a class, what is the search path for this class.
<?phpnamespace A;use BD, CE as F;// Function call foo(); // First try to call the function foo() defined in the namespace "A" // Then try to call the global function" foo"foo(); // Call the global space function "foo" myfoo(); // Call the function "foo" defined in the namespace "Amy" F(); // First try to call function "F" defined in namespace "A" // Then try to call global function "F" // Class reference new B(); // Create class "B" defined in namespace "A" An object of class "AB" new D(); // If not found, try to autoload class "AB" new D(); // Using import rules, create an object of class "D" defined in namespace "B" // If not found If found, try to automatically load class "BD" new F(); // Using import rules, create an object of class "E" defined in namespace "C" // If not found, try to autoload class "CE" new B(); // Create an object of class "B" defined in global space // If not found, try to autoload class "B" new D(); // Create an object of class "D" defined in global space // If not found, try to autoload class "D" new F(); // Create an object of class "F" defined in the global space // If not found, try to autoload class "F" // Call a static method or namespace function in another namespace Bfoo(); // Call function "foo" in namespace "AB" B::foo(); // Call method "foo" of class "B" defined in namespace "A" // If class "AB" is not found , then try to automatically load class "AB" D::foo(); // Use import rules to call the "foo" method of class "D" defined in namespace "B" // If class "BD" " If not found, try to automatically load the class "BD"Bfoo(); // Call the function "foo" in the namespace "B" B::foo(); // Call the function in the global space Class "B" The "foo" method // If class "B" is not found, try to autoload class "B" // A static method or function in the current namespace AB::foo(); // Call namespace "A" "foo" method of class "B" defined in A" // If class "AAB" is not found, try to autoload class "AAB"AB::foo() ; // Call the "foo" method of class "B" defined in namespace "A" // If class "AB" is not found, try to autoload class "AB"?>
Name resolution follows the following rules:
Calls to fully qualified names of functions, classes and constants are resolved at compile time. For example, new AB resolves to class AB .
All unqualified names and qualified names (not fully qualified names) are converted at compile time according to the current import rules. For example, if namespace ABC was imported as C , then calls to CDe() would be translated to ABCDe() .
Within a namespace, all qualified names that are not converted according to import rules will have the current namespace name prepended to them. For example, if CDe() is called within namespace AB , CDe() will be converted to ABCDe() .
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 ABC is imported as C, new C() is converted to new ABC() .
Within a namespace (e.g. AB), function calls to unqualified names are resolved at runtime. For example, a call to function foo() is parsed like this:
Find a function named ABfoo() in the current namespace
Try to find and call function foo() in global space.
Calls to unqualified names or qualified name classes (non-fully qualified names) within a namespace (e.g. AB ) are resolved at runtime. The following is the parsing process of calling new C() and new DE() : Parsing of new C() :
Find classes ABC in the current namespace.
Try to autoload classes ABC .
Analysis of new DE() :Prepend the class name with the current namespace name to become: ABDE and then look for that class.
Try to autoload class ABDE .
In order to refer to a global class in the global namespace, the fully qualified name new C() must be used.