Pull to refresh

Как использовать пространства имён в PHP, Часть 2: импортирование, псевдонимы и правила разбора имён

PHP *
Translation
Original author: Craig Buckler
image
В части 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 (на английском / на русском)
  1. Вызов квалифицированных функций разрешается во время компилирования.
  2. Все квалифицированные имена транслируются во время компиляции в соответствии с текущими импортированными пространствами имён. К примеру, если импортировано пространство имён A::B::C, вызов C::D::e() будет транслирован как A::B::C::D::e().
  3. Внутри пространства имён все квалифицированные имена транслируются согласно правилам импортирования, например, если пространство имён A\B\C импортируется как C, вызов C\D\e() транслируется в A\B\C\D\e().
  4. Неквалифицированные имена классов транслируются во время компиляции в соответствии с текущими импортированными пространствами имён и полные имена заменяют короткие импортированные имена, например, если класс C в пространстве имён A\B импортирован как X, new X() будет транслирован в new A\B\C().
  5. Внутри пространства имён вызов неквалифицированных функций интерпретируется во время компиляции. Например, если MyFunction() вызвана в пределах пространства имён A\B, PHP сперва ищет функцию \A\B\MyFunction(). Если она не будет найдена, PHP будет искать \MyFunction() в глобальном пространстве.
  6. Вызовы неквалифицированных или квалифицированных имён классов интерпретируется во время компиляции. Например, если мы вызываем new C() в пределах пространства имён A\B, PHP будет искать класс A\B\C. Если он не будет найден, это приведет к попытке автозагрузки A\B\C.

В следующей части: ключевые слова и автозагрузка.

Читайте также:


Как использовать пространства имен в PHP, Часть 1: Основы
Как использовать пространства имён в PHP, Часть 3: Ключевые слова и автозагрузка

Примечания:



A/ Замечания, поправки, указания на неточности и проч. — приветствуются!

B/ Код подсвечен с помощью Source Code Highlighter.
Tags:
Hubs:
Total votes 39: ↑34 and ↓5 +29
Views 17K
Comments Comments 55