PHP Namespaces
PHP namespaces were introduced in PHP 5.3. If you have studied C# and Java, namespaces are not new to you. However, they hold significant importance in PHP.
PHP namespaces can address the following two types of issues:
- Conflicts between user-written code and PHP's internal classes/functions/constants or third-party classes/functions/constants.
- Creating aliases (or short) names for long identifier names (usually defined to alleviate the first issue), enhancing the readability of source code.
Defining Namespaces
By default, all constants, classes, and function names are placed in the global namespace, just as they were before PHP supported namespaces.
Namespaces are declared using the namespace
keyword. If a file contains a namespace, it must declare the namespace before any other code. The syntax is as follows:
<?php
// Define code in the 'MyProject' namespace
namespace MyProject;
// ... code ...
You can also define different namespaces in the same file, like this:
<?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 bracketed syntax below.
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
?>
Combining global non-namespaced code with namespaced code can only be done using the bracketed syntax. Global code must be enclosed in a namespace
statement without a name, like this:
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
The only valid code before declaring a namespace is the declare
statement for defining the source file encoding. No non-PHP code, including whitespace, can appear before the namespace declaration.
<?php
declare(encoding='UTF-8'); // Defining multiple namespaces and code not in a namespace
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
The following code will result in a syntax error:
<html>
<?php
namespace MyProject; // A fatal error - the namespace must be the first statement in the script
?>
Sub-Namespaces
Similar to the relationship between directories and files, PHP namespaces allow specifying hierarchical namespace names. Therefore, namespace names can be defined in a hierarchical manner:
<?php
namespace MyProject\Sub\Level; // Declare a hierarchical single namespace
const CONNECT_OK = 1;
class Connection { /* ... */ }
function Connect() { /* ... */ }
?>
The example above 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 PHP namespaces can be referenced in three ways:
-
Non-qualified 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 currentnamespace\foo
. If the code using foo
is global, not enclosed in any namespace, foo
will be resolved to foo
. Warning: If the function or constant in the namespace is not defined, the non-qualified function name or constant name will be resolved to the global function name or constant name.
-
Qualified name, or a name with a 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, not enclosed in any namespace, foo
will be resolved to subnamespace\foo
.
-
Fully qualified name, or a name with a global prefix operator, such as $a = new \currentnamespace\foo();
or \currentnamespace\foo::staticmethod();
. In this case, foo
is always resolved to the literal name currentnamespace\foo
in the code.
Here is an example 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() {}
}
/* Non-qualified name */
foo(); // Resolves to function Foo\Bar\foo
foo::staticmethod(); // Resolves to class Foo\Bar\foo, method staticmethod
echo FOO; // Resolves to constant Foo\Bar\FOO
/* Qualified name */
subnamespace\foo(); // Resolves to function Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // Resolves to class Foo\Bar\subnamespace\foo,
// and method staticmethod
echo subnamespace\FOO; // Resolves to constant Foo\Bar\subnamespace\FOO
/* Fully qualified name */
\Foo\Bar\foo(); // Resolves to function Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // Resolves to class Foo\Bar\foo, method staticmethod
echo \Foo\Bar\FOO; // Resolves to constant Foo\Bar\FOO
?>
Note that you can access any global class, function, or constant using a fully qualified name, such as \strlen()
or \Exception
or \INI_ALL
.
Accessing global classes, functions, and constants within a namespace:
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // Calls global function strlen
$b = \INI_ALL; // Accesses global constant INI_ALL
$c = new \Exception('error'); // Instantiates global class Exception
?>
Namespaces and Dynamic Language Features
The implementation of PHP namespaces is influenced by the dynamic nature of the language itself. Therefore, to convert the following code to use namespaces for dynamic access to elements.
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
?>
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
/* If using double quotes, use "\\namespacename\\classname" */
$a = '\namespacename\classname';
$obj = new $a; // prints namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // prints namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // prints namespacename\funcname
$b = '\namespacename\funcname';
$b(); // prints namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // prints namespaced
echo constant('namespacename\constname'), "\n"; // prints namespaced
?>
The namespace Keyword and the __NAMESPACE__ Constant
PHP supports two abstract ways to access elements within the current namespace: the __NAMESPACE__ magic constant and the namespace keyword.
The value of the __NAMESPACE__ constant is a string that contains the current namespace name. In global, non-namespaced code, it contains an empty string.
__NAMESPACE__ Example, code within a namespace
<?php
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // prints "MyProject"
?>
__NAMESPACE__ Example, global code
<?php
echo '"', __NAMESPACE__, '"'; // prints ""
?>
The __NAMESPACE__ constant is useful for dynamically creating names, for example:
Using __NAMESPACE__ to dynamically create names
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\\' . $classname;
return new $a;
}
?>
The namespace keyword can be used to explicitly access elements within the current namespace or sub-namespaces. It is equivalent to the self operator in classes.
Namespace operator, code within a namespace
<?php
namespace MyProject;
use blah\blah as mine; // imports the blah\blah namespace and defines an alias mine
mine\mine(); // calls the 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 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
?>
Using Namespaces: Aliases/Imports
PHP Namespaces support two ways of aliasing or importing: aliasing class names, or aliasing namespace names.
In PHP, aliases are implemented using the use
operator. Below is an example using all three possible import methods:
Importing/aliasing with the
use
operator<?php namespace foo; use My\Full\Classname as Another; // The following example is the same as use My\Full\NSname as NSname use My\Full\NSname; // Importing a global class use \ArrayObject; $obj = new namespace\Another; // instantiates object of class foo\Another $obj = new Another; // instantiates object of class My\Full\Classname NSname\subns\func(); // calls function My\Full\NSname\subns\func $a = new ArrayObject(array(1)); // instantiates object of class ArrayObject // If not using "use \ArrayObject", it would instantiate an object of class foo\ArrayObject ?>
Multiple
use
statements in one line<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // instantiates object of class My\Full\Classname NSname\subns\func(); // calls function My\Full\NSname\subns\func ?>
Importing is performed at compile time, but dynamic class names, function names, or constant names are not affected.
- Importing and dynamic names
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // instantiates object of class My\Full\Classname $a = 'Another'; $obj = new $a; // instantiates object of class Another ?>
Additionally, importing affects only unqualified and qualified names. Fully qualified names are definite and thus not affected by importing.
- Importing and fully qualified names
<?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 to Global Function/Constant
<?php
namespace MyProject;
function func() {
echo "Calling MyProject\func()\n";
}
function sub\func() {
echo "Calling MyProject\sub\func()\n";
}
class cname {
static function method() {
echo "Calling MyProject\cname::method()\n";
}
}
const CONSTANT = "MyProject\CONSTANT";
namespace\func(); // calls function MyProject\func()
namespace\sub\func(); // calls function MyProject\sub\func()
namespace\cname::method(); // calls static 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
?>
Within a namespace, when PHP encounters an unqualified class, function, or constant name, it uses different prioritization strategies to resolve the name. Class names are always resolved to the names in the current namespace. Therefore, when accessing system internal or non-namespaced class names, you must use the fully qualified name, for example:
- Accessing a global class within a namespace
<?php namespace A\B\C; class Exception extends \Exception {} $a = new Exception('hi'); // $a is an object of class A\B\C\Exception $b = new \Exception('hi'); // $b is an object of class Exception $c = new ArrayObject; // Fatal error, class A\B\C\ArrayObject not found ?>
For functions and constants, if they do not exist in the current namespace, PHP will fall back to using the functions or constants in the global namespace.
- Fallback to global functions/constants within a namespace
<?php namespace A\B\C; const E_ERROR = 45; function strlen($str) { return \strlen($str) - 1; } echo E_ERROR, "\n"; // Outputs "45" echo INI_ALL, "\n"; // Outputs "7" - uses the global constant INI_ALL echo strlen('hi'), "\n"; // Outputs "1" if (is_array('hi')) { // Outputs "is not array" echo "is array\n"; } else { echo "is not array\n"; } ?>
Global Space
If no namespace is defined, all class and function definitions are in the global space, just as they were before PHP introduced the concept of namespaces. Prepending a name with a \ indicates that the name is in the global space, even if it is within another namespace.
Example of using the global space
<?php
namespace A\B\C;
/* This function is A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // Calls the global fopen function
return $f;
}
?>
Namespace Order
Since the introduction of namespaces, one of the most common mistakes is understanding the search path for a class when it is used.
<?php
namespace A;
use B\D, C\E as F;
// Function calls
foo(); // First tries to call the function foo() defined in namespace "A"
// Then tries to call the global function "foo"
\foo(); // Calls the global space function "foo"
my\foo(); // Calls the function "foo" defined in namespace "A\my"
F(); // First tries to call the function "F" defined in namespace "A"
// Then tries to call the global function "F"
// Class references
new B(); // Creates an object of the class "B" defined in namespace "A"
// If not found, attempts to autoload class "A\B"
new D(); // Uses the import rules, creates an object of the class "D" defined in namespace "B"
// If not found, attempts to autoload class "B\D"
new F(); // Uses the import rules, creates an object of the class "E" defined in namespace "C"
// If not found, attempts to autoload class "C\E"
new \B(); // Creates an object of the class "B" defined in the global space
// If not found, attempts to autoload class "B"
new \D(); // Creates an object of the class "D" defined in the global space
// If not found, attempts to autoload class "D"
new \F(); // Creates an object of the class "F" defined in the global space
// If not found, attempts to autoload class "F"
// Calling static methods or namespace functions in another namespace
B\foo(); // Calls the function "foo" in namespace "A\B"
B::foo(); // Calls the "foo" method of the class "B" defined in namespace "A"
// If class "A\B" is not found, attempts to autoload class "A\B"
D::foo(); // Uses the import rules, calls the "foo" method of the class "D" defined in namespace "B"
// If class "B\D" is not found, attempts to autoload class "B\D"
\B\foo(); // Calls the function "foo" in namespace "B"
\B::foo(); // Calls the "foo" method of class "B" in the global namespace
// If class "B" is not found, attempts to autoload class "B"
// Static method or function in the current namespace
A\B::foo(); // Calls the "foo" method of class "B" defined in namespace "A\A"
// If class "A\A\B" is not found, attempts to autoload class "A\A\B"
\A\B::foo(); // Calls the "foo" method of class "B" defined in namespace "A"
// If class "A\B" is not found, attempts to autoload class "A\B"
?>
Name resolution follows these rules:
Calls to fully qualified functions, classes, and constants are resolved at compile time. For example, new \A\B resolves to class A\B.
All unqualified and qualified names (non-fully qualified names) are translated at compile time according to the current import rules. For example, if namespace A\B\C is imported as C, then the call to C\D\e() is translated to A\B\C\D\e().
Within a namespace, all qualified names not translated according to import rules have the current namespace name prepended to them. For example, within namespace A\B, a call to C\D\e() is translated to A\B\C\D\e().
Unqualified class names are translated at compile time according to the current import rules (using the full name instead of the short import name). For example, if namespace A\B\C is imported as C, then new C() is translated to new A\B\C().
Within a namespace (e.g., A\B), calls to unqualified function names are resolved at runtime. For example, the call to function foo() is resolved as follows:
Looks for a function named A\B\foo() in the current namespace.
Attempts to find and call the function foo() in the global namespace.
Within a namespace (e.g., A\B), calls to unqualified or qualified class names (non-fully qualified names) are resolved at runtime. Here is the resolution process for new C() and new D\E():
Looks for class A\B\C in the current namespace.
Attempts to autoload class A\B\C.
Prepends the current namespace name to the class name to become A\B\D\E, then looks for that class.
Attempts to autoload class A\B\D\E. ```