Name resolution rules
Оновлено: 11.05.2023
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Для цілей цих правил прийняття рішень наведемо кілька важливих визначень:
- Визначення імен у просторі імен
- Некваліфіковане ім'я
- Це ідентифікатор без роздільника простору назв, наприклад, Foo
- Кваліфіковане ім'я
- Це ідентифікатор з роздільником простору імен, наприклад, Foo\Bar
- Повністю кваліфіковане ім'я
- Це ідентифікатор з роздільником простору назв, який починається з роздільника простору назв, наприклад \Foo\Bar. Простір назв \Foo також є повністю кваліфікованим іменем.
- Відносне ім'я
- Це ідентифікатор, який починається з простору назв, наприклад, простір назв \Foo\Bar.
Це ідентифікатор без роздільника простору імен, наприклад, Foo
Це ідентифікатор з роздільником простору імен, наприклад, Foo\Bar
Це ідентифікатор з роздільником простору назв, який починається з роздільника простору назв, наприклад \Foo\Bar. Простір назв \Foo також є повністю кваліфікованою назвою.
Це ідентифікатор, що починається з простору назв, наприклад, простір назв\Foo\Bar.
Імена вирішуються відповідно до цих правил:
Повністю кваліфіковані імена завжди перетворюються на ім'я без провідного роздільника простору імен. Наприклад, \A\B перетворюється на A\B. Відносні імена завжди перетворюються на ім'я з простором назв, заміненим на поточний простір назв. Якщо ім'я зустрічається у глобальному просторі назв, префікс namespace\ вилучається. Наприклад, простір назв\A у просторі назв X\Y перетворюється на X\Y\A. Таке саме ім'я у глобальному просторі імен перетворюється на A. Для кваліфікованих імен перший сегмент імені перекладається відповідно до поточної таблиці імпорту класів/просторів імен. Наприклад, якщо простір імен A\B\C імпортовано як C, ім'я C\D\E буде перетворено на A\B\C\D\E. Для кваліфікованих імен, якщо не застосовується жодне правило імпорту, до імені додається поточний простір імен. Наприклад, ім'я C\D\E у просторі назв A\B перетворюється на A\B\C\D\E. Для некваліфікованих імен, ім'я перекладається згідно з поточною таблицею імпорту для відповідного типу символів. Це означає, що імена класів перекладаються відповідно до таблиці імпорту класів/просторів імен, імена функцій - відповідно до таблиці імпорту функцій, а констант - відповідно до таблиці імпорту констант. Наприклад, після використання A\B\C; таке використання, як new C() перетворюється на ім'я A\B\C(). Аналогічно, після використання функції A\B\fn; таке використання, як fn() розпізнається як ім'я A\B\fn. Для некваліфікованих імен, якщо не застосовується жодне правило імпорту і ім'я посилається на символ типу класу, додається поточний простір імен. Наприклад, new C() всередині простору імен A\B розпізнається як ім'я A\B\C. Для некваліфікованих імен, якщо не застосовується правило імпорту і ім'я посилається на функцію або константу, а код знаходиться за межами глобального простору імен, ім'я розпізнається під час виконання програми. Якщо припустити, що код знаходиться у просторі імен A\B, то ось як буде вирішено виклик функції foo(): Шукається функція з поточного простору імен: A\B\foo(). Намагається знайти і викликати глобальну функцію foo().
Шукає функцію з поточного простору імен: A\B\foo(). Намагається знайти і викликати глобальну функцію foo().
Приклад #1 Проілюстровано роздільну здатність імен
<?php
namespace A;
use B\D, C\E as F;
// function calls
foo(); // first tries to call "foo" defined in namespace "A"
// then calls global function "foo"
\foo(); // calls function "foo" defined in global scope
my\foo(); // calls function "foo" defined in namespace "A\my"
F(); // first tries to call "F" defined in namespace "A"
// then calls global function "F"
// class references
new B(); // creates object of class "B" defined in namespace "A"
// if not found, it tries to autoload class "A\B"
new D(); // using import rules, creates object of class "D" defined in namespace "B"
// if not found, it tries to autoload class "B\D"
new F(); // using import rules, creates object of class "E" defined in namespace "C"
// if not found, it tries to autoload class "C\E"
new \B(); // creates object of class "B" defined in global scope
// if not found, it tries to autoload class "B"
new \D(); // creates object of class "D" defined in global scope
// if not found, it tries to autoload class "D"
new \F(); // creates object of class "F" defined in global scope
// if not found, it tries to autoload class "F"
// static methods/namespace functions from another namespace
B\foo(); // calls function "foo" from namespace "A\B"
B::foo(); // calls method "foo" of class "B" defined in namespace "A"
// if class "A\B" not found, it tries to autoload class "A\B"
D::foo(); // using import rules, calls method "foo" of class "D" defined in namespace "B"
// if class "B\D" not found, it tries to autoload class "B\D"
\B\foo(); // calls function "foo" from namespace "B"
\B::foo(); // calls method "foo" of class "B" from global scope
// if class "B" not found, it tries to autoload class "B"
// static methods/namespace functions of current namespace
A\B::foo(); // calls method "foo" of class "B" from namespace "A\A"
// if class "A\A\B" not found, it tries to autoload class "A\A\B"
\A\B::foo(); // calls method "foo" of class "B" from namespace "A"
// if class "A\B" not found, it tries to autoload class "A\B"
?>