(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Before discussing the use of namespaces, it is important to understand how PHP knows which namespaced element your code is requesting. A simple analogy can be made between PHP namespaces and a filesystem. There are three ways to access a file in a file system:
foo.txt
. This resolves to
currentdirectory/foo.txt
where currentdirectory
is the
directory currently occupied. So if the current directory is
/home/foo
, the name resolves to /home/foo/foo.txt
.
subdirectory/foo.txt
. This resolves
to currentdirectory/subdirectory/foo.txt
.
/main/foo.txt
. This resolves
to /main/foo.txt
.
$a = new foo();
or
foo::staticmethod();
. If the current namespace is
currentnamespace
, this resolves to
currentnamespace\foo
. If
the code is global, non-namespaced code, this resolves to foo
.
One caveat: unqualified names for functions and constants will
resolve to global functions and constants if the namespaced function or constant
is not defined. See Using namespaces:
fallback to global function/constant for details.
$a = new subnamespace\foo();
or
subnamespace\foo::staticmethod();
. If the current namespace is
currentnamespace
, this resolves to
currentnamespace\subnamespace\foo
. If
the code is global, non-namespaced code, this resolves to subnamespace\foo
.
$a = new \currentnamespace\foo();
or
\currentnamespace\foo::staticmethod();
. This always resolves
to the literal name specified in the code, currentnamespace\foo
.
Here is an example of the three kinds of syntax in actual code:
file1.php
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
file2.php
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* Unqualified 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,
// 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 to access any global
class, function or constant, a fully qualified name can be used, such as
\strlen() or \Exception or
\INI_ALL
.
Example #1 Accessing global classes, functions and constants from 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
?>
Syntax for extending classes in namespaces is still the same.
Lets call this Object.php:
<?php
namespace com\rsumilang\common;
class Object{
// ... code ...
}
?>
And now lets create a class called String that extends object in String.php:
<?php
class String extends com\rsumilang\common\Object{
// ... code ...
}
?>
Now if you class String was defined in the same namespace as Object then you don't have to specify a full namespace path:
<?php
namespace com\rsumilang\common;
class String extends Object
{
// ... code ...
}
?>
Lastly, you can also alias a namespace name to use a shorter name for the class you are extending incase your class is in seperate namespace:
<?php
namespace com\rsumilang\util;
use com\rsumlang\common as Common;
class String extends Common\Object
{
// ... code ...
}
?>
- Richard Sumilang
<?php
namespace Foo;
try {
// Something awful here
// That will throw a new exception from SPL
}
catch (Exception as $ex) {
// We will never get here
// This is because we are catchin Foo\Exception
}
?>
Instead use fully qualified name for the exception to catch it
<?php
namespace Foo;
try {
// something awful here
// That will throw a new exception from SPL
}
catch (\Exception as $ex) {
// Now we can get here at last
}
?>
Well variables inside namespaces do not override others since variables are never affected by namespace but always global:
"Although any valid PHP code can be contained within a namespace, only four types of code are affected by namespaces: classes, interfaces, functions and constants. "
Source: "Defining Namespaces"
http://www.php.net/manual/en/language.namespaces.definition.php
It seems the file system analogy only goes so far. One thing that's missing that would be very useful is relative navigation up the namespace chain, e.g.
<?php
namespace MyProject {
class Person {}
}
namespace MyProject\People {
class Adult extends ..\Person {}
}
?>
That would be really nice, especially if you had really deep namespaces. It would save you having to type out the full namespace just to reference a resource one level up.
Working with variables can overwrite equal variables in other namespaces
<?php // php5 - package-version : 5.3.5-1ubuntu7.2
namespace
main
{}
namespace
main\sub1
{
$data = 1;
}
namespace
main\sub2
{
echo $data;// 1
$data = 2;
}
namespace
main\sub1
{
echo $data;// 2
$data = 1;
}
namespace
{
echo $data;// 1
}
?>