Learning Objectives – after this chapter you will be able to:
- Explain the two problems namespaces solve: name collisions and very long names.
- Declare namespaces and sub-namespaces, including several in one file.
- Refer to names using unqualified, qualified and fully qualified forms.
- Import and alias classes, functions and constants with
use. - Use the global space, the
namespaceoperator and the__NAMESPACE__constant.
What is a Namespace?
In the broadest sense, namespaces are a way of encapsulating items. You meet this idea in many places. In any operating system, directories group related files and act as a namespace for the files within them: the file foo.txt can exist in both /home/greg and /home/other, but two copies of foo.txt cannot exist in the same directory. To access foo.txt from outside /home/greg, we prepend the directory name with the directory separator: /home/greg/foo.txt. The same principle extends to namespaces in programming.
In PHP, namespaces solve two problems that authors of libraries and applications meet when they create reusable classes and functions:
- Name collisions between your code and internal PHP classes, functions and constants, or third-party code.
- The need to write Extra_Long_Names (invented to avoid the first problem) – namespaces let you alias (shorten) them, improving readability.
PHP namespaces group related classes, interfaces, functions and constants. Here is the general syntax:
<?php
namespace my\name;
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass; // my\name\MyClass
$c = new \my\name\MyClass; // fully qualified name
$a = strlen('hi'); // falls back to the global strlen()
$d = namespace\MYCONST; // the namespace operator
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d);Why Do We Need Namespaces?
As your PHP code library grows, there is an increasing risk of accidentally re-defining a function or class name that has been declared before. The problem gets worse when you add third-party components or plug-ins: what if two or more of them implement a Database or User class? Namespaces solve such name collisions. All modern PHP frameworks (Laravel, Symfony) and Composer packages rely on them.
Defining Namespaces
By default, all constant, class and function names are placed in the global space – as they were before PHP supported namespaces (PHP 5.3).
Namespaces are declared with the namespace keyword. A file containing a namespace must declare it at the top of the file before any other code – with one exception: the declare keyword. No non-PHP code, not even white space or HTML, may precede the declaration:
<html> <?php namespace MyProject; // fatal error – namespace must be the first statement in the script
Unlike any other PHP construct, the same namespace may be defined in several files, splitting its contents across the file system.
Declaring a single namespace
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection
{
public function info() { return "Connection class in " . __NAMESPACE__; }
}
function connect() { return "MyProject\\connect() called"; }Declaring sub-namespaces
Like directories and files, namespaces can have a hierarchy:
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 2;
class Connection
{
public function info() { return "Connection class in " . __NAMESPACE__; }
}
function connect() { return __FUNCTION__ . "() called"; }This creates the constant MyProject\Sub\Level\CONNECT_OK, the class MyProject\Sub\Level\Connection and the function MyProject\Sub\Level\connect. Both files define a class named Connection – and there is no collision:
<?php require "lib1.php"; require "lib2.php"; $a = new MyProject\Connection(); $b = new MyProject\Sub\Level\Connection(); echo $a->info() . "<br>"; echo $b->info() . "<br>"; echo MyProject\connect() . "<br>"; echo MyProject\Sub\Level\connect() . "<br>"; echo "CONNECT_OK values: " . MyProject\CONNECT_OK . " and " . MyProject\Sub\Level\CONNECT_OK; ?>
Connection class in MyProject Connection class in MyProject\Sub\Level MyProject\connect() called MyProject\Sub\Level\connect() called CONNECT_OK values: 1 and 2
Several Namespaces in One File
Multiple namespaces may be declared in one file, with two possible syntaxes. The simple combination syntax (one namespace X; after another) is not recommended. Use the bracketed syntax:
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { public static function start() { return "MyProject connection started"; } }
function connect() { return "MyProject\\connect()"; }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { public static function start() { return "AnotherProject connection started"; } }
function connect() { return "AnotherProject\\connect()"; }
}
namespace { // global code
echo MyProject\connect() . "<br>";
echo MyProject\Connection::start() . "<br>";
echo AnotherProject\Connection::start();
}
?>MyProject\connect() MyProject connection started AnotherProject connection started
To combine global (non-namespaced) code with namespaced code, only the bracketed syntax is allowed; the global code is placed in a namespace { … } block with no name. No PHP code may exist outside the brackets except an opening declare statement.
Putting several namespaces in one file is discouraged as a coding practice. The main use is to combine several scripts into one file for deployment. Normally each class has its own file (see autoloading, Chapter 17).
Referring to Names
| Kind of name | Example | Resolved (inside namespace App) |
|---|---|---|
| Unqualified | Connection | App\Connection |
| Qualified | Sub\Connection | App\Sub\Connection |
| Fully qualified | \MyProject\Connection | MyProject\Connection (leading \ = from the global root) |
Importing and Aliasing with use
The ability to refer to an external fully qualified name with an alias (importing) is an important feature of namespaces – similar to creating symbolic links to files in Unix. In PHP, aliasing is done with the use operator. You can import classes, interfaces, namespaces and – since PHP 5.6 – functions (use function) and constants (use const).
<?php namespace Shop; require "lib1.php"; require "lib2.php"; use MyProject\Connection as Main; // alias a class use MyProject\Sub\Level\Connection; // import with its own short name use MyProject\Sub\Level; // alias a namespace use function MyProject\connect; // import a function use const MyProject\CONNECT_OK; // import a constant use ArrayObject; // import a global class $x = new Main(); $y = new Connection(); echo $x->info() . "<br>"; echo $y->info() . "<br>"; echo Level\connect() . "<br>"; echo connect() . "<br>"; echo "CONNECT_OK = " . CONNECT_OK . "<br>"; $arr = new ArrayObject([1, 2, 3]); // without "use ArrayObject" PHP would look for Shop\ArrayObject echo "ArrayObject count: " . count($arr); ?>
Connection class in MyProject Connection class in MyProject\Sub\Level MyProject\Sub\Level\connect() called MyProject\connect() called CONNECT_OK = 1 ArrayObject count: 3
Several imports can be combined in one statement: use My\Full\Classname as Another, My\Full\NSname;. Since PHP 7 related imports can also be grouped: use MyProject\Sub\Level\{Connection, function connect};.
Importing is performed at compile time, so it does not affect dynamic class names held in strings: with $a = 'Another'; new $a; PHP looks for the global class Another, not the alias. Dynamic names must always be fully qualified.
The Global Space
Without any namespace definition, all classes and functions are placed in the global space. Prefixing a name with \ specifies that the name is required from the global space even inside a namespace:
<?php
namespace A\B\C;
/* This function is A\B\C\strlen */
function strlen($s)
{
return "my own strlen: " . \strlen($s) . " characters"; // call the global strlen
}
echo strlen("namespace") . "<br>"; // calls A\B\C\strlen
echo \strlen("namespace") . "<br>"; // calls PHP's strlen
echo "Current namespace: " . __NAMESPACE__;
?>my own strlen: 9 characters 9 Current namespace: A\B\C
When PHP meets an unqualified function or constant name inside a namespace and no such name exists in the namespace, it falls back to the global function or constant – that is why strlen('hi') works in any namespace. For classes there is no fallback: new ArrayObject inside namespace Shop means Shop\ArrayObject unless you import it or write \ArrayObject.
The __NAMESPACE__ Constant and the namespace Operator
__NAMESPACE__ is a string that always contains the current namespace name; in the global space it is an empty string. The keyword namespace can also be used as an operator to refer explicitly to the current namespace, e.g. namespace\connect().
<?php
namespace App\Lib1;
function hello() { return "Hello from " . __FUNCTION__; }
echo __NAMESPACE__ . "<br>"; // outputs: App\Lib1
echo namespace\hello() . "<br>"; // current namespace
$fn = __NAMESPACE__ . '\hello'; // dynamic name must be fully qualified
echo $fn();
?>App\Lib1 Hello from App\Lib1\hello Hello from App\Lib1\hello
Key Takeaways
- Namespaces group classes, interfaces, functions and constants and prevent name collisions.
- Declare with
namespace Name;as the first statement of the file; sub-namespaces use\. - Use bracketed syntax for several namespaces (and global code) in one file.
- Names can be unqualified, qualified or fully qualified (
\from the root). useimports and aliases (as);use functionanduse constimport functions and constants.- Functions and constants fall back to the global space; classes do not.
__NAMESPACE__holds the current namespace;namespace\xrefers to it explicitly.
Program File
Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch16 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.
Question / Answer (15 questions)
MCQ Test : Check Your Understanding (5 questions)
Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.
Bibliography/References
The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.
- The PHP Group. (n.d.). PHP Manual – Namespaces overview. https://www.php.net/manual/en/language.namespaces.rationale.php
- The PHP Group. (n.d.). PHP Manual – Defining multiple namespaces in the same file. https://www.php.net/manual/en/language.namespaces.definitionmultiple.php
- The PHP Group. (n.d.). PHP Manual – Using namespaces: Aliasing/Importing. https://www.php.net/manual/en/language.namespaces.importing.php
- The PHP Group. (n.d.). PHP Manual – Global space. https://www.php.net/manual/en/language.namespaces.global.php
- The PHP Group. (n.d.). PHP Manual – namespace keyword and __NAMESPACE__ magic constant. https://www.php.net/manual/en/language.namespaces.nsconstants.php