
В части 1, мы обсуждали для чего нужны пространства имён (namespaces) в PHP, и что обозначает зарезервированное слово namespace. В этой статье мы исследуем оператор use и способ, которым PHP разрешает имена пространств имён.
В целях данной статьи мы будем использовать два почти идентичных кода, единственное различие которых — в их пространствах имён:
lib1.php:
- <?php
- // application library 1
- namespace App\Lib1;
-
- const MYCONST = 'App\Lib1\MYCONST';
-
- function MyFunction() {
- return __FUNCTION__;
- }
-
- class MyClass {
- static function WhoAmI() {
- return __METHOD__;
- }
- }
- ?>
lib2.php:
- <?php
- // application library 2
- namespace App\Lib2;
-
- const MYCONST = 'App\Lib2\MYCONST';
-
- function MyFunction() {
- return __FUNCTION__;
- }
-
- class MyClass {
- static function WhoAmI() {
- return __METHOD__;
- }
- }
- ?>
Прежде чем мы начнём, давайте вспомним несколько определений из PHP терминологии:
Полное квалифицированное имя (Fully-qualified name)
Любой PHP код может ссылаться на полное квалифицированное имя — идентификатор, начинающийся с разделителя пространства имён (т. е. обратного слэша — backslash), например: \App\Lib1\MYCONST, \App\Lib2\MyFunction() и т.д.
В полных квалифицированных именах нет никакой двусмысленности. Начальный обратный слэш действует аналогичным образом как и путь к файлу, обозначая «корень (root)» глобального пространства. Если бы мы выполняли различные MyFunction() в нашем глобальном пространстве, они могли бы быть вызваны из lib1.php или lib2.php с помощью \MyFunction().
Полные квалифицированные имена полезны для одноразового вызова функций или инициализации объектов. Однако, когда вы делаете много вызовов, они становятся непрактичными. Как мы узнаем ниже, PHP предлагает другие варианты в этих случаях.
Квалифицированное имя (Qualified name)
Идентификатор, имеющий как минимум хотя бы один разделитель пространства имён (namespace separator, фактически — обратный слэш), например Lib1\MyFunction().
Неквалифицированное имя (Unqualified name)
Идентификатор без разделителя пространства имён, например MyFunction().
Работа с одинаковыми пространствами имён
Обсудим следующий код:
myapp1.php:
- <?php
- namespace App\Lib1;
-
- require_once('lib1.php');
- require_once('lib2.php');
-
- header('Content-type: text/plain');
- echo MYCONST . "\n";
- echo MyFunction() . "\n";
- echo MyClass::WhoAmI() . "\n";
- ?>
Хотя мы присоединили и lib1.php и lib2.php, идентификаторы MYCONST, MyFunction и MyClass будут относиться только к lib1.php. Это произойдет потому что код myapp1.php расположен в едином с App\Lib1 пространстве имён:
результат:
- App\Lib1\MYCONST
- App\Lib1\MyFunction
- App\Lib1\MyClass::WhoAmI
Импортирование пространств имён (Namespace Importing)
Пространства имён могут быть импортированы с помощью оператора use, например:
myapp2.php:
- <?php
- use App\Lib2;
-
- require_once('lib1.php');
- require_once('lib2.php');
-
- header('Content-type: text/plain');
- echo Lib2\MYCONST . "\n";
- echo Lib2\MyFunction() . "\n";
- echo Lib2\MyClass::WhoAmI() . "\n";
- ?>
Вы можете импортировать с помощью use одно или несколько пространств имён, разделяя их запятой. В данном примере, мы импортировали пространство имён App\Lib2. Мы все еще не можем ссылаться прямо на MYCONST, MyFunction или MyClass потому что наш код находится в глобальном пространстве и PHP будет искать их именно там. Но если мы добавим префикс «Lib2\», они станут квалифицированными именами, а PHP станет искать их в импортированных пространствах имён, пока не найдет полного совпадения.
результат:
- App\Lib2\MYCONST
- App\Lib2\MyFunction
- App\Lib2\MyClass::WhoAmI
Псевдонимы пространства имён (Namespace Aliases)
Псевдонимы пространства имён, возможно, самая полезная конструкция. Псевдонимы позволяют ссылаться на длинные пространства имён с помощью короткого имени.
myapp3.php:
- <?php
- use App\Lib1 as L;
- use App\Lib2\MyClass as Obj;
-
- header('Content-type: text/plain');
- require_once('lib1.php');
- require_once('lib2.php');
-
- echo L\MYCONST . "\n";
- echo L\MyFunction() . "\n";
- echo L\MyClass::WhoAmI() . "\n";
- echo Obj::WhoAmI() . "\n";
- ?>
Первый оператор use определяет App\Lib1 как «L». Любое квалифицированное имя, использующее «L», будет преобразовано во время компиляции в «App\Lib1». Поэтому, мы скорее сошлемся на L\MYCONST или L\MyFunction, чем на полное квалифицированное имя.
Второй оператор use более интересен. Он определяет «Obj» как псевдоним для класса «MyClass» в пределах пространства имён App\Lib2\. Эта операция применительна только для классов — не для констант или функций. Теперь мы можем использовать new Obj(), или вызывать статические методы, как показано выше.
результат:
- App\Lib1\MYCONST
- App\Lib1\MyFunction
- App\Lib1\MyClass::WhoAmI
- App\Lib2\MyClass::WhoAmI
Правила разбора имён
Имена PHP идентификаторов разрешаются следующими правилами пространств имён. для более полной информации, обратитесь к руководству по PHP (на английском / на русском)
- Вызов квалифицированных функций разрешается во время компилирования.
- Все квалифицированные имена транслируются во время компиляции в соответствии с текущими импортированными пространствами имён. К примеру, если импортировано пространство имён A::B::C, вызов C::D::e() будет транслирован как A::B::C::D::e().
- Внутри пространства имён все квалифицированные имена транслируются согласно правилам импортирования, например, если пространство имён A\B\C импортируется как C, вызов C\D\e() транслируется в A\B\C\D\e().
- Неквалифицированные имена классов транслируются во время компиляции в соответствии с текущими импортированными пространствами имён и полные имена заменяют короткие импортированные имена, например, если класс C в пространстве имён A\B импортирован как X, new X() будет транслирован в new A\B\C().
- Внутри пространства имён вызов неквалифицированных функций интерпретируется во время компиляции. Например, если MyFunction() вызвана в пределах пространства имён A\B, PHP сперва ищет функцию \A\B\MyFunction(). Если она не будет найдена, PHP будет искать \MyFunction() в глобальном пространстве.
- Вызовы неквалифицированных или квалифицированных имён классов интерпретируется во время компиляции. Например, если мы вызываем new C() в пределах пространства имён A\B, PHP будет искать класс A\B\C. Если он не будет найден, это приведет к попытке автозагрузки A\B\C.
В следующей части: ключевые слова и автозагрузка.
Читайте также:
Как использовать пространства имен в PHP, Часть 1: Основы
Как использовать пространства имён в PHP, Часть 3: Ключевые слова и автозагрузка
Примечания:
A/ Замечания, поправки, указания на неточности и проч. — приветствуются!
B/ Код подсвечен с помощью Source Code Highlighter.



комментарии (55)