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

(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\fn;, использование fn() разрешается как A\B\fn.
  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\DC\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"
?>