Продолжаем знакомиться с пространствами имен. В предыдущей статье мы узнали, что такое пространства имен, зачем они нужны, узнали что инклюдить файлы все равно придется, и рассмотрели пример о том, как же ими пользоваться, как определять и т.д.
В этой статье рассмотрим остальные аспекты пространств имен, которые не были затронуты ранее.
Глобальное пространство имен
В конце прошлой статьи я говорил об относительности путей подключения пространств имен и сравнивал их с директориями в операционке. Так вот, как и в UNIX системах, например, есть корневой элемент. Адрес корня сервера имеет вид - /
Аналогично этому существует корневое пространство имен - \
Все стандартные функции языка, все ваши классы и функции, константы, описанные без привязки к пространству имен, на самом деле будут принадлежать глобальному пространству имен.
Если вы определили функцию вне пространства имен, то обратиться к ней можно будет двумя способами:
function foo()
{
return 'Абсолютно бесполезная функция';
}
echo foo(); // = Абсолютно бесполезная функция
echo \foo(); // = Абсолютно бесполезная функция
Поэтому вы всегда можете быть уверенными, что если вы вызываете функцию \print_r() - это будет всегда функция, встроенная в php.
Да да - вы не ослышались - внутри своего пространства имен можно определить функцию, которая будет иметь название, аналогичное встроенной функции. Вот пример:
namespace Space;
function print_r($s)
{
echo $s . ' - а вот и не print_r :Р';
}
$toPrint = 'На печать';
print_r($toPrint); // = На печать - а вот и не print_r :Р
\print_r($toPrint); // = На печать
Поэтому - не стоит бездумно переопределять встроенные функции, т.к. это может ввести в заблуждение неопытных разработчиков.
Ну и будьте благоразумны при построении пути из неймспейсов при разработке. Если в вашем файле определено пространство имен, то все вызовы будут строиться от текущего пространства имен. Находясь в namespace Space вы должны осознавать, что вызов функции без префикса из пространств имен приведет к вызову функции из текущего пространства, а если вы вызываете функцию с пространством имен, то либо пространство должно быть относительным от текущего, либо должно начинаться с глобального
namespace Universe;
function wow()
{
echo 'Universe';
}
namespace Universe\Galaxy;
function wow()
{
echo 'Universe\Galaxy';
}
wow(); // = Universe\Galaxy
\Universe\Galaxy\wow(); // = Universe\Galaxy
Universe\Galaxy\wow(); // = Fatal Error
\Universe\wow(); // = Universe
Таким образом какой вывод можно сделать из того, что мы уже изучили - то что пространство имен является частью имени сущности php. Эти самые имена теперь делятся на 3 вида:
- Неполные имена. Это привычные нам имена без пространств имен. Например - $a = new ClassName; function functionName() {}
- Полные (ваш КО) имена. Имена, которые содержат в названии пространство имен. Например - $a = new Galaxy\ClassName;
Причем, если текущее пространство имен - Universe, то данное имя класса будет приведено к Universe\Galaxy\ClassName. Такие имена я бы предпочитал называть относительными (мое имхо, по аналогии со ссылками и путями) - Абсолютные имена. Это те имена, которые начинаются с глобального пространства имен и содержат полный путь из неймспейсов. Например - $a = new \Universe\Galaxy\ClassName;
NAMESPACE и namespace
Как и для многих сущностей в php, для пространства имен существует зарезервированная константа, именуется она как NAMESPACE и содержит она в себе имя пространства имен, в контексте которого вызывается. Если в предыдущем примере подменить строку после echo на NAMESPACE , то получится точно такой-же вывод.
namespace Universe;
function wow()
{
echo __NAMESPACE__;
}
namespace Universe\Galaxy;
function wow()
{
echo __NAMESPACE__;
}
wow(); // = Universe\Galaxy
\Universe\Galaxy\wow(); // = Universe\Galaxy
\Universe\wow(); // = Universe
Соответственно, усваивая информацию о том, что пространство имен является частью имени сущностей, можно проверить, что в константах CLASS, METHOD и FUNCTION тоже теперь содержится пространство имен.
Кстати, если использовать вывод NAMESPACE находясь в глобальном пространстве имен, то будет выведена пустая строка, а не обратный слеш.
Есть еще ключевое слово namespace, которое указывает на необходимость явного указания текущего пространства имен. Хороший пример приведен в оф. документации, транслирую его сюда:
namespace MyProject;
use blah\blah as mine; // см. "Использование пространств имен: импорт/создание псевдонима имени"
blah\mine(); // вызывает функцию MyProject\blah\mine()
namespace\blah\mine(); // вызывает функцию MyProject\blah\mine()
namespace\func(); // вызывает функцию MyProject\func()
namespace\sub\func(); // вызывает функцию MyProject\sub\func()
namespace\cname::method(); // вызывает статический метод "method" класса MyProject\cname
$a = new namespace\sub\cname(); // Создает экземпляр класса MyProject\sub\cname
$b = namespace\CONSTANT; // присваивает значение константы MyProject\CONSTANT переменной $b
А также использование этого ключевого слова в глобальном пространстве имен:
namespace\func(); // вызывает функцию func()
namespace\sub\func(); // вызывает функцию sub\func()
namespace\cname::method(); // вызывает статический метод "method" класса cname
$a = new namespace\sub\cname(); // Создает экземпляр класса sub\cname
$b = namespace\CONSTANT; // присваивает значение константы CONSTANT переменной $b
Прочие тонкости
Если вы используете динамические имена сущностей, то стоит учесть одну небольшую особенность. В строке, содержащей имя, например, класса каждый обратный слеш должен быть экранирован, если вы хотите использовать его для пространства имен.
$className = '\\Bitrix\\Iblock\\ElementTable';
$className::query()->addFilter('IBLOCK_ID',1)->exec();
Нельзя использовать пространство имен, вложенное в пространство имен (скобочная нотация)
// Не правильно
namespace A {
namespace B {
function c() {};
}
}
//Правильно
namespace A\B;
function c() {};
Об остальных аспектах читайте в официальной документации, там есть еще моменты не рассмотренные мной, но я считаю их достаточно редкими кейсами, и если вы с ними сталкиваетесь. значит вы достаточно опытны для самостоятельного их разрешения.
Про неймспейсы - все