[PHP 5 >= 5.3.0, PHP 7, PHP 8]
For the purposes of these resolution rules, here are some important definitions:
Namespace name definitions Unqualified name This is an identifier without a namespace separator, such as Foo
This is an identifier with a namespace separator, such as Foo\Bar
This is
an identifier with a namespace separator that begins with a namespace separator, such as \Foo\Bar
. The namespace \Foo
is also a fully qualified name.
This is an identifier starting with namespace
, such as namespace\Foo\Bar
.
Names are resolved following these resolution rules:
- Fully qualified names always resolve to the name without leading namespace separator. For instance
\A\B
resolves toA\B
. - Relative names always resolve to the name with
namespace
replaced by the current namespace. If the name occurs in the global namespace, thenamespace\
prefix is stripped. For examplenamespace\A
inside namespaceX\Y
resolves toX\Y\A
. The same name inside the global namespace resolves toA
. - For qualified names the first segment of the name is translated according to the current class/namespace import table. For example, if the namespace
A\B\C
is imported asC
, the nameC\D\E
is translated toA\B\C\D\E
. - For qualified names, if no import rule applies, the current namespace is prepended to the name. For example, the name
C\D\E
inside namespaceA\B
, resolves toA\B\C\D\E
. - For unqualified names, the name is translated according to the current import table for the respective symbol type. This means that class-like names are translated according to the class/namespace import
table, function names according to the function import table and constants according to the constant import table. For example, after
use A\B\C;
a usage such asnew C[]
resolves to the nameA\B\C[]
. Similarly, afteruse function A\B\fn;
a usage such asfn[]
resolves to the nameA\B\fn
. - For unqualified names, if no import rule applies and the name refers to a class-like symbol, the current namespace is prepended. For example
new C[]
inside namespaceA\B
resolves to nameA\B\C
. - For unqualified names, if no import rule applies and the name refers to a function or constant and the code is outside the global namespace, the name is resolved at runtime. Assuming the code is in namespace
A\B
, here is how a call to functionfoo[]
is resolved:- It looks for a function from the current namespace:
A\B\foo[]
. - It tries to find and call the global function
foo[]
.
- It looks for a function from the current namespace:
Example #1 Name resolutions illustrated
kdimi ¶
11 years ago
If you like to declare an __autoload function within a namespace or class, use the spl_autoload_register[] function to register it and it will work fine.
rangel ¶
13 years ago
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:
->Say you have the following directory structure:
- root
| - loader.php
| - ns
| - foo.php
->foo.php
Cheers!
-> loader.php
If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors.
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.
safakozpinar at NOSPAM dot gmail dot com ¶
11 years ago
As working with namespaces and using [custom or basic] autoload structure; magic function __autoload must be defined in global scope, not in a namespace, also not in another function or method.
Kavoir.com ¶
8 years ago
For point 4, "In example, if the namespace A\B\C is imported as C" should be "In example, if the class A\B\C is imported as C".
llmll ¶
7 years ago
The mentioned filesystem analogy fails at an important point:
Namespace resolution *only* works at declaration time. The compiler fixates all namespace/class references as absolute paths, like creating absolute symlinks.
You can't expect relative symlinks, which should be evaluated during access -> during PHP runtime.
In other words, namespaces are evaluated like __CLASS__ or self:: at parse-time. What's *not* happening, is the pendant for late static binding like static:: which resolves to the current class at runtime.
So you can't do the following:
namespace Alpha;
class Helper {
public static $Value = "ALPHA";
}
class Base {
public static function Write[] {
echo Helper::$Value;
}
}
namespace Beta;
class Helper extends \Alpha\Helper {
public static $Value = 'BETA';
}
class Base extends \Alpha\Base {}
\Beta\Base::Write[]; // should write "BETA" as this is the executing namespace context at runtime.
If you copy the write[] function into \Beta\Base it works as expected.
rangel ¶
13 years ago
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:
->Say you have the following directory structure:
- root
| - loader.php
| - ns
| - foo.php
->foo.php
Cheers!
-> loader.php
If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors.
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.
CJ Taylor ¶
8 years ago
It took me playing with it a bit as I had a hard time finding documentation on when a class name matches a namespace, if that's even legal and what behavior to expect. It IS explained in #6 but I thought I'd share this with other souls like me that see it better by example. Assume all 3 files below are in the same directory.
I hope this is useful, particularly for those that are trying to wrap your head around this 5.3 feature.file1.php
file2.php
Depending upon what you're building [example: a module, plugin, or package on a larger application], sometimes declaring a class that matches a namespace makes sense or may even be required. Just be aware that if you try to reference any class that shares the same namespace, omit the namespace unless you do it globally like the examples above.
anrdaemon at freemail dot ru ¶
6 years ago
Namespaces may be case-insensitive, but autoloaders most often do.
Do yourself a service, keep your cases consistent with file names, and don't overcomplicate autoloaders beyond necessity.
Something like this should suffice for most times: