Пространство имен
Пространство имен
Foo - неполное имя
Foo\Bar - полное имя
\Foo\Bar - абсолютное имя
namespace\Foo\Bar - относительное имя
Абсолютные имена разрешаются в имя без ведущего разделителя пространства имён. Например, \A\B разрешается в A\B
Относительные имена разрешаются в имя с заменой ключевого слова namespace текущим пространством имён. Если имя встречается в глобальном пространстве имён, префикс namespace\ удаляется. Например, имя namespace\A внутри пространства имён X\Y разрешается в X\Y\A. То же имя в глобальном пространстве имён разрешается в A.
В полных именах первый сегмент имени преобразовывается с учётом текущей таблицы импорта класса или пространства имён. Например, если пространство имён A\B\C импортировано как C, то имя C\D\E преобразуется в A\B\C\D\E
В полных именах, если не применялось правило импорта, текущее пространство имён добавляется к имени. Например, имя C\D\E внутри пространства имён A\B разрешится в A\B\C\D\E
Неполные имена преобразовываются с учётом текущей таблицы импорта и типа элемента. То есть имена как у классов преобразовываются с учётом таблицы импорта классов или пространств имён, имена функций — с учётом таблицы импорта функций, а константы — таблицы импорта констант. Например, при записи use A\B\C;, вызов new C() разрешается в A\B\C(). Аналогично, при записи use function A\B\foo; вызов foo() разрешается в A\B\foo
В начало неполных имён, если не применялось правило импорта и имя относится к элементу с именем как у класса, добавляется текущее пространство имён. Например, имя класса в выражении new C() внутри пространства имён A\B разрешится в имя A\B\C
В неполных именах, если не применялось правило импорта и имя относится к функции или константе, а код лежит за пределами глобального пространства имён, имя разрешается при выполнении. Вот как разрешится вызов функции foo() в коде в пространстве имён A\B:
Выполняется поиск функции из текущего пространства имён: A\B\foo()
PHP пытается найти и вызвать функцию foo() из глобального пространства имён
Подробные примеры в источнике: https://www.php.net/manual/ru/language.namespaces.rules.php
Пространство имен - способ инкапсуляции объектов, подобно тому как директории инкапсулируют файлы
С помощью пространств имен устраняют конфликты между кодом и внутренними или внешними классами, функциями и константами
С помощью пространств имен можно создавать псевдонимы для длинных имен с целью улучшить читаемость кода
Пространства имен помогают сгруппировать логически связанные классы, интерфейсы, функции, константы
Замечание: Имена пространств имён регистронезависимы
namespace mySpace;
class MyClass
{
function MyFunc()
{
echo "MyFunc<br>";
}
}
function MyFunc()
{
echo "MyFunc";
}
const MYCONST = 1;
$a = new MyClass;
$a->MyFunc();
$b = new \mySpace\MyClass;
$b->MyFunc();
Пространства имён в файлах объявляют в начале, перед любым другим кодом, кроме зарезервированного слова declare
Только выражение declare разрешено помещать перед объявлением пространства имён, чтобы определить кодировку исходного файла. В дополнение, никакой код, кроме PHP-кода, нельзя размещать перед объявлением пространства имён, включая лишние пробелы
Одно и то же пространство имён, в отличие от остальных конструкций PHP, допустимо определять в нескольких файлах, что помогает распределять содержание файлов по файловой системе
Так же как файлы и каталоги, пространства имён PHP разрешают создавать иерархию имён. Поэтому имя пространства разрешено определять с подуровнями:
namespace MyProject\Sub\Level;
В одном файле разрешено объявлять несколько пространств имён. Есть два разрешённых синтаксиса:
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
Вместо него лучше пользоваться альтернативным синтаксисом со скобками
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
Практика написания кода настоятельно не рекомендует объединять пространства имён в одном файле
Для объединения кода в глобальном пространстве имён с кодом в других пространствах имён пользуются только синтаксисом со скобками. Глобальный код должен быть помещён в конструкцию описания пространства имён без указания имени
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // Глобальный код
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
Никакой PHP-код нельзя размещать за пределами скобок пространства имён, кроме начального выражения declare
declare(encoding='UTF-8');
namespace MyProject {
...
#test1.php
namespace Foo\Bar\subnamespace;
function foo() { echo "Foo\Bar\subnamespace<br>";}
#test.php
namespace Foo\Bar;
include "test1.php";
function bar() { echo "Foo\Bar<br>";}
bar(); #Foo\Bar
subnamespace\foo(); #Foo\Bar\subnamespace
\Foo\Bar\bar(); #Foo\Bar
\Foo\Bar\subnamespace\foo(); #Foo\Bar\subnamespace
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"<br>";
}
}
$obj = new \namespacename\classname; # namespacename\classname::__construct
__METHOD__
Выводит название метода
function __construct()
{
echo __METHOD__,"\n";
}
Выводит название функции
function funcname()
{
echo __FUNCTION__,"\n";
}
Псевдонимирование и импорт
PHP умеет ссылаться на внешнее абсолютное имя по псевдониму или импортировать константы, функции, классы, интерфейсы, трейты, перечисления и пространства имен
Псевдоним имени создается с помощью ключевого слова use
Ключевое слово use должно быть указано в самом начале файла (в глобальной области) или внутри объявления пространства имён. Это нужно, потому что импорт выполняется во время компиляции, а не во время исполнения, поэтому его нельзя ограничить блоком кода
Правила импорта задают на каждый файл отдельно. Поэтому присоединяемые файлы НЕ будут наследовать правила импорта из родительского файла
#Это пространство которое включает в себя все что ниже
namespace foo;
use My\Full\Classname as Another, My\Full\MyName;
#Далее к My\Full\Classname можно обращать по псевдониму Another
$obj = new Another; // Создаёт объект класса My\Full\Classname
use My\Full\NSname;
#Импорт глобального объекта
use ArrayObject;
#Импортирование функции
use function My\Full\functionName;
#Создание псевдонима функции
use function My\Full\functionName as func;
#Импорт константы
use const My\Full\CONSTANT;
#Создает объект класса My\Full\Classname
$obj = new Another;
#Вызывает функцию My\Full\NSname\subns\func
NSname\subns\func();
#Создаёт объект класса ArrayObject
#без выражения use ArrayObject был бы создан объект класса foo\ArrayObject
$a = new ArrayObject(array(1));
#вызывает функцию My\Full\functionName
func();
#выводит содержимое константы My\Full\CONSTANT
echo CONSTANT;
#Создаёт экземпляр класса foo\Another
$obj = new namespace\Another;
MyName\subns\func(); // Вызывает функцию My\Full\MyName\subns\func
$obj = new Another; // Создаёт объект класса My\Full\Classname
#импорт распространяется только на неполные и полные имена
#На абсолютные имена операция импорта не влияет
$obj = new \Another; // Создаёт объект класса Another
$obj = new Another\thing; // Создаёт объект класса My\Full\Classname\thing
$obj = new \Another\thing; // Создаёт объект класса Another\thing
Классы, функции и константы, импортируемые из одного и того же пространства имён (namespace), разрешено группировать в одном выражении с ключевым словом use
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// Эквивалентно следующему групповому объявлению с ключевым словом use
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
Возврат к глобальному пространству
Имена классов разрешаются в текущее имя пространства имён. Поэтому, чтобы получить доступ ко внутреннему классу или пользовательскому классу вне пространства имён, необходимо обращаться к ним по абсолютному имени
PHP будет обращаться к глобальным функциям или константам, если функция или константа не существует в текущем пространстве имён
namespace A\B\C;
const E_ERROR = 45;
function strlen($str)
{
return \strlen($str) - 1;
}
echo E_ERROR, "\n"; // Выводит 45
echo INI_ALL, "\n"; // Выводит «7» — возвращается к глобальной константе INI_ALL
echo strlen('hi'), "\n"; // Выводит «1»
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // Переменная $a — это объект класса A\B\C\Exception
$b = new \Exception('hi'); // Переменная $b — это объект класса Exception
$c = new ArrayObject; // Фатальная ошибка, класс A\B\C\ArrayObject не найден
Источники
Связанные темы
Оператор разрешения видимости в php
Позднее статическое связывание
Методы создания экземпляра класса в php
Автоматическая загрузка классов
Наследование с помощью extends в php
Конструкторы и деструкторы в php