Основы пространств имён
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Прежде чем обсуждать работу с пространствами имён, важно понять, как PHP узнаёт,
какие элементы из пространства имён запрашиваются в коде. Можно провести
аналогию между пространствами имён PHP и файловой системой. Есть три способа обратиться
к файлу в файловой системе:
-
Относительное имя файла наподобие
foo.txt
разрешится
в currentdirectory/foo.txt
, где currentdirectory
— текущая
директория, в которой мы находимся. Тогда, если текущая директория —
/home/foo
, то имя преобразуется в /home/foo/foo.txt
.
-
Относительное имя пути наподобие
subdirectory/foo.txt
разрешится
в currentdirectory/subdirectory/foo.txt
.
-
Абсолютное имя пути наподобие
/main/foo.txt
останется
таким же: /main/foo.txt
.
Тот же принцип сохранится при разрешении элементов из пространств имён PHP. Например,
имя класса разрешают указывать тремя способами:
-
Неполное имя, или имя класса без префикса, наподобие
$a = new foo();
или
foo::staticmethod();
. Если текущее пространство имён —
currentnamespace
, то это имя разрешится
в currentnamespace\foo
. В коде в глобальном
пространстве имён имя останется таким же: foo
.
Предостережение: неполные имена функций и констант будут разрешатся
в глобальные функции и константы, если они не определены в текущем пространстве имён.
Подробнее об этом рассказано в разделе
«
Пространства имён: возврат к глобальному пространству для функций и констант
».
-
Полное имя, или имя класса с префиксами наподобие
$a = new subnamespace\foo();
или
subnamespace\foo::staticmethod();
. Если текущее пространство имён —
currentnamespace
, то это имя разрешится
в currentnamespace\subnamespace\foo
. В коде в глобальном
пространстве имён имя разрешится в subnamespace\foo
.
-
Абсолютное имя, или имя с префиксом в начале,
который указывает на глобальное пространство имён наподобие
$a = new \currentnamespace\foo();
или
\currentnamespace\foo::staticmethod();
. Такое имя разрешается
в буквальное имя, заданное в коде: currentnamespace\foo
.
Вот пример трёх видов синтаксиса в реальном коде:
Обратите внимание, что для доступа к глобальным
классам, функциям или константам разрешается указывать абсолютное имя, например,
\strlen(), \Exception
или \INI_ALL
.
Пример #1 Доступ к глобальным классам, функциям и константам из пространства имён
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // Вызывает глобальную функцию strlen
$b = \INI_ALL; // Получает доступ к глобальной константе INI_ALL
$c = new \Exception('error'); // Создаёт экземпляр глобального класса Exception
?>
richard at richard-sumilang dot com ¶16 years ago
Syntax for extending classes in namespaces is still the same.
Lets call this Object.php:
<?php
namespace com\rsumilang\common;
class Object{
}
?>
And now lets create a class called String that extends object in String.php:
<?php
class String extends com\rsumilang\common\Object{
}
?>
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
{
}
?>
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
{
}
?>
- Richard Sumilang
Anonymous ¶10 years ago
<?php
namespace Foo;
try {
}
catch (Exception as $ex) {
}
?>
Instead use fully qualified name for the exception to catch it
<?php
namespace Foo;
try {
}
catch (\Exception as $ex) {
}
?>
Lukas Z ¶13 years ago
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
tom at tomwardrop dot com ¶12 years ago
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.
philip dot preisser at arcor dot de ¶13 years ago
Working with variables can overwrite equal variables in other namespaces
<?php namespace
main
{}
namespace
main\sub1
{
$data = 1;
}
namespace
main\sub2
{
echo $data;$data = 2;
}
namespace
main\sub1
{
echo $data;$data = 1;
}
namespace
{
echo $data;}
?>