Правила разрешения имён

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

Для этих правил здесь приведены несколько важных определений:

Определения имени пространства имён
Неполное имя

Это идентификатор без разделителя пространств имён, например, Foo

Полное имя

Это идентификатор с разделителем пространств имён, например, Foo\Bar

Абсолютное имя

Это идентификатор с разделителем пространств имён, который начинается с разделителя пространств имён, например, \Foo\Bar. Пространство имён \Foo также является абсолютным именем.

Относительное имя

Это идентификатор, начинающийся с namespace, такой как namespace\Foo\Bar.

Имена разрешаются согласно следующим правилам:

  1. Абсолютные имена всегда разрешаются без ведущего разделителя пространства имён. Например, \A\B разрешается в A\B.
  2. Относительные имена всегда разрешаются в имена с заменой namespace на текущее пространство имён. Если имя встречается в глобальном пространстве имён, префикс namespace\ просто удаляется. К примеру namespace\A внутри пространства имён X\Y разрешается в X\Y\A. То же самое имя в глобальном пространстве имён разрешается в A.
  3. Для полных имён первый сегмент преобразуется в соответствии с текущей таблицей импорта класса или пространства имён. Например, пространство имён A\B\C импортировано как C, тогда имя C\D\E преобразуется в A\B\C\D\E.
  4. Для полных имён, если не применяется никакого правила импорта, текущее пространство имён добавляется к имени. Например, имя C\D\E внутри пространства имён A\B, преобразуется в A\B\C\D\E.
  5. Для неполных имён имена преобразуются текущей таблице импорта в зависимости от типа элемента. Это означает, что имена классов преобразуются согласно таблице импорта классов, имена функций - согласно таблице импорта функций и константы согласно таблице импорта констант. К примеру, после use A\B\C;, использование new C() разрешается как A\B\C(). Аналогично, после use function A\B\foo;, использование foo() разрешается как A\B\foo.
  6. Неполные имена, если отсутствуют ограничения в таблице импорта и если они используются как класс, то они разрешаются с префиксом текущего пространства имён. Например, new C() внутри пространства имён A\B разрешаются как A\B\C.
  7. Неполные имена, если отсутствуют ограничения в таблице импорта и если они используются как функция или константа, а код находится не в глобальном пространстве имён, имена разрешаются во время исполнения. Например код, в пространстве имён A\B, вызывающий функцию foo(), разрешается так:
    1. Производится поиск функции из текущего пространства имён: A\B\foo().
    2. PHP пытается найти и вызвать функцию глобального пространства foo().

Пример #1 Примеры разрешения имён

<?php
namespace A;
use
B\D, C\E as F;

// вызовы функций

foo(); // сперва пытается вызвать "foo", определённую в пространстве имён "A",
// затем вызывает глобальную функцию "foo"

\foo(); // вызывает функцию "foo", определённую в глобальном пространстве

my\foo(); // вызывает функцию "foo", определённую в пространстве "A\my"

F(); // сперва пытается вызвать "F", определённую в пространстве имён "A",
// затем вызывает глобальную функцию "F"

// ссылки на классы

new B(); // создаёт объект класса "B", определённого в пространстве имён "A".
// если не найден, то пытается сделать автозагрузку класса "A\B"

new D(); // используя правила импорта, создаёт объект класса "D", определённого в пространстве имён "B"
// если не найден, то пытается сделать автозагрузку класса "B\D"

new F(); // используя правила импорта, создаёт объект класса "E", определённого в пространстве имён "C"
// если не найден, то пытается сделать автозагрузку класса "C\E"

new \B(); // создаёт объект класса "B", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "B"

new \D(); // создаёт объект класса "D", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "D"

new \F(); // создаёт объект класса "F", определённого в глобальном пространстве,
// если не найден, то пытается сделать автозагрузку класса "F"

// статические методы/функции пространства имён из другого пространства имён

B\foo(); // вызывает функцию "foo" из пространства имён "A\B"

B::foo(); // вызывает метод "foo" из класса "B", определённого в пространстве имён "A"
// если класс "A\B" не найден, то пытается сделать автозагрузку класса "A\B"

D::foo(); // используя правила импорта, вызывает метод "foo" класса "D", определённого в пространстве имён "B"
// если класс "B\D" не найден, то пытается сделать автозагрузку класса "B\D"

\B\foo(); // вызывает функцию "foo" из пространства имён "B"

\B::foo(); // вызывает метод "foo" класса "B" из глобального пространства
// если класс "B" не найден, то пытается сделать автозагрузку класса "B"

// статические методы/функции пространства имён из текущего пространства имён

A\B::foo(); // вызывает метод "foo" класса "B" из пространства имён "A\A"
// если класс "A\A\B" не найден, то пытается сделать автозагрузку класса "A\A\B"

\A\B::foo(); // вызывает метод "foo" класса "B" из пространства имён "A"
// если класс "A\B" не найден, то пытается сделать автозагрузку класса "A\B"
?>