1

Тема: Цікаві ефекти в Namespace

Може хтось пояснити такий спецефект Namespace?
PHP без проблем читає такий код:

<?php
namespace NameA;
class A extends \NameB\B {}

namespace NameB;
class B {}

Але говорить Fatal error: Class 'NameB\B' not found in ...file, якщо читає такий код:

<?php
namespace NameA;
class A extends \NameB\B {}

namespace NameB;
class B extends \NameC\C {}

namespace NameC;
class C {}

Як це розуміти? Чому коли спочатку оголошуєш namespace NameC; перед namespace NameB;, то все працює:

<?php
namespace NameA;
class A extends \NameB\B {}

namespace NameC;
class C {}

namespace NameB;
class B extends \NameC\C {}
Подякували: ailkiv1

2

Re: Цікаві ефекти в Namespace

Угу, схоже на баг інтерпритатора, Доречі якщо поставити А в кінець, то теж буде працювати.

3

Re: Цікаві ефекти в Namespace

Може щось підкажуть на stackoverflow

4

Re: Цікаві ефекти в Namespace

Підкажуть писати в різних файлах)))

5

Re: Цікаві ефекти в Namespace

Я думаю в тест кейсах було, що можна всеж шукати в глибину один не оголошений клас далі по файлу, але не далі як один. Тобто в першому випадку ви просто використовуєте не задокументовану фічу, яка по ідеї теж не мала би працювати.

6 Востаннє редагувалося ktretyak (24.12.2014 22:22:58)

Re: Цікаві ефекти в Namespace

Читаю в доках для extends PHP 4, що:

Classes must be defined before they are used! If you want the class Named_Cart to extend the class Cart, you will have to define the class Cart first. If you want to create another class called Yellow_named_cart based on the class Named_Cart you have to define Named_Cart first. To make it short: the order in which the classes are defined is important.

Мабуть це правило діє і для PHP 5. Але все одно залишається питання, чому все ж таки це застереження не спрацьовує "один раз".

7

Re: Цікаві ефекти в Namespace

Ну не задокументована фіча. Почали робити, а потім забили. Сказали що PHP не для збоченців, хай перше декларують, а потім вже використовують.

8

Re: Цікаві ефекти в Namespace

Мабуть, все ж таки, як я і думав раніше, це більше пов'язано з особливістю автозавантаження класів.

В доках говориться, що є відмінність між пошуком класа і його автозавантаженням. Тобто якщо певний клас не знайдено в місці його декларування, то PHP намагатиметься зробити автозавантаження. Припускаю, що це саме той випадок, коли проходить перший прохід "далі" в коді. І якщо тоді знаходиться таки оголошення класа, але його батьківський клас не знайдено, то в PHP закінчується ліміт кроків на пошук одного класа чи його ланцюжка наслідувань, а саме:
1. Пошук серед вже завантажених класів
2. Спроба автозавантаження

9

Re: Цікаві ефекти в Namespace

Класне питання підняв, тримай +1.
Добряче звивини довелося напружити, щоб знайти істину

Вся фішка у компіляторі.
Класи PHP в С зберігаються у списку.
Коли код компілюється цей список наповнюються класами які зустрічаються при компіляції.
Всі класи які зустрічаються компілюються у вже готовий opcode, але без traits, implements, extends.
Але є один нюанс якщо у класа є extends на клас який вже у списку є, код парента зразу вставиться у дочірній клас

Усі traits, implements, і extends які не попали у виняток розширюють клас вже під час виконання opcode

Саме тому даний код буде працювати:

<?php
namespace NameA;
class A extends \NameB\B {}
 
namespace NameC;
class C {}
 
namespace NameB;
class B extends \NameC\C {}

Класи \NameC\C, \NameB\B будуть повноціно скомпільовані (готові до використанням) станом на початок виконання скрипту. І тому при виконанні "A extends \NameB\B" віртуальна машина зможе вже нормально розширити клас А.

<?php
namespace NameA;
class A extends \NameB\B {}
 
namespace NameB;
class B extends \NameC\C {}
 
namespace NameC;
class C {}

Тут тільки клас \NameC\C будуть повноціно скомпільований станом на початок виконання скрипту. І тому при виконанні "A extends \NameB\B" віртуальна машина знатиме про клас \NameB\B, але також знатиме що він ще неготовий до використання (щоб він був готовий треба спочатку його розширити класом NameC\C, а про це вже віртуальна машина не знає бо це інструкція Opcode яка йде далі)

Подякували: Vo_Vik1

10

Re: Цікаві ефекти в Namespace

Тобто PHP все ж таки спочатку компілює, а не зразу йде інтерпритація.... Цікаво-цікаво.