| 1 | # PHP 8.x — язык и семантика (фундаментальный проход) |
| 2 | |
| 3 | **Назначение:** целостная карта **семантики PHP 8.x** (ориентир **8.4+**): типы, объекты, ошибки, пространства имён, граничные случаи. Мир **`software.php`**. Хронология фич по мажорам с **5.x** — `kb-php-versions-and-evolution-v1.md`. Рантайм/SAPI/Composer — в `kb-php-fundamentals-v1.md`; веб-слой — в `kb-php-web-sessions-io-v1.md`. |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ### 1. Модель выполнения и единица компиляции |
| 8 | |
| 9 | - **Fact:** PHP компилирует скрипт в **opcode** и исполняет в рантайме Zend VM; `include`/`require` — отдельные компиляции при первом попадании (с учётом OPcache). Нет отдельного «линковера» как в C; порядок подключения файлов влияет на видимость классов/функций до автозагрузки. |
| 10 | - **Heuristic:** полагаться на **PSR-4 + один entrypoint** вместо длинных цепочек `require`; для логики порядка инициализации использовать явный composer autoload и композицию, не «кто первый подключился». |
| 11 | |
| 12 | --- |
| 13 | |
| 14 | ### 2. Переменные, присваивание, ссылки |
| 15 | |
| 16 | - **Fact:** переменные — контейнеры zval; **присваивание** объектов — по handle (не глубокое копирование); **присваивание массивов** — копирование по значению (copy-on-write); оператор `&` создаёт **псевдоним**. |
| 17 | - **Heuristic:** избегать `&` в публичных API; с `foreach ($arr as &$v)` сбрасывать ссылку `unset($v)` после цикла — иначе последующие присваивания ломают массив неочевидно. |
| 18 | |
| 19 | --- |
| 20 | |
| 21 | ### 3. Скаляры и `strict_types` |
| 22 | |
| 23 | - **Fact:** без `declare(strict_types=1)` внутри файла встроенные и пользовательские функции могут применять **слабые приведения** скаляров к объявленным типам; со `strict_types=1` несовместимые скаляры дают `TypeError`. |
| 24 | - **Heuristic:** для новых модулей с контрактами — `strict_types=1`; граница HTTP/JSON (всё строки) — явно валидировать/кастовать до вызова строгого слоя. |
| 25 | |
| 26 | --- |
| 27 | |
| 28 | ### 4. Union, intersection, mixed, never, void |
| 29 | |
| 30 | - **Fact:** union (`string|int`), intersection только для классов (`A&B`), `mixed` — верх, `void` — только возврат «ничего», `never` — не возвращает (throw/exit/бесконечный цикл). Несовместимые union на рантайме → `TypeError`. |
| 31 | - **Heuristic:** `mixed` не использовать как «не знаю» там, где можно перечислить union; `never` документирует завершение потока — полезно для статанализа. |
| 32 | |
| 33 | --- |
| 34 | |
| 35 | ### 5. Массивы как хеш-таблица |
| 36 | |
| 37 | - **Fact:** PHP-массив — упорядоченная хеш-таблица; ключи `int` и числовые строки приводятся по правилам индексации; отрицательные и большие int — валидны; `[]` — push. |
| 38 | - **Heuristic:** для «словарей» не полагаться на неявное приведение строковых числовых ключей; для JSON-совместимости — нормализовать ключи перед `json_encode`. |
| 39 | |
| 40 | --- |
| 41 | |
| 42 | ### 6. Строки, кодировки, байты vs символы |
| 43 | |
| 44 | - **Fact:** строка PHP — **байтовая** последовательность; Unicode-семантика — через `mb_*` / `intl`; с 8.4 расширен mbstring (`mb_trim` и др.). |
| 45 | - **Heuristic:** весь пользовательский текст — явная кодировка (UTF-8); не резать строки по байтам для UI — `mb_substr`; для бинарных данных — не проходить через «текстовые» фильтры. |
| 46 | |
| 47 | --- |
| 48 | |
| 49 | ### 7. Функции: сигнатуры, значения по умолчанию, variadic |
| 50 | |
| 51 | - **Fact:** параметры с default должны идти после обязательных; `...$rest` собирает остаток; именованные аргументы (8.0+) привязаны к имени параметра; порядок с именованными гибкий. |
| 52 | - **Heuristic:** публичные функции — именованные аргументы только при стабильных именах параметров (рефакторинг ломает call sites). |
| 53 | |
| 54 | --- |
| 55 | |
| 56 | ### 8. Замыкания и стрелочные функции |
| 57 | |
| 58 | - **Fact:** замыкания — объекты `Closure`; захват `use ($x)` по значению или `&$x` по ссылке; короткие fn автозахватывают переменные по значению одним выражением. |
| 59 | - **Heuristic:** не захватывать тяжёлые сервисы в fn без нужды; для долгоживущих очередей — сериализация closure ограничена — не хранить closures в сессии. |
| 60 | |
| 61 | --- |
| 62 | |
| 63 | ### 9. Классы, свойства, конструктор |
| 64 | |
| 65 | - **Fact:** свойства с типами проверяются при присваивании; **constructor property promotion** (8.0+) сокращает boilerplate; **readonly** (8.1+) — инициализация один раз (гибкость с clone ограничена). |
| 66 | - **Heuristic:** DTO/Value objects — `readonly` + типы; мутабельные сущности — явный контракт изменения состояния. |
| 67 | |
| 68 | --- |
| 69 | |
| 70 | ### 10. Property hooks и asymmetric visibility (8.4) |
| 71 | |
| 72 | - **Fact:** **property hooks** позволяют встроить get/set без ручных методов; **asymmetric visibility** — разный доступ на чтение и запись у свойства. |
| 73 | - **Heuristic:** при миграции легаси не смешивать «голые public поля» и hooks в одной иерархии без дисциплины; статанализаторы должны поддерживать 8.4. |
| 74 | |
| 75 | --- |
| 76 | |
| 77 | ### 11. Наследование, static, late static binding |
| 78 | |
| 79 | - **Fact:** одиночное наследование классов; `static::` разрешается в runtime по вызываемому классу (LSB); `self::` — лексический класс. |
| 80 | - **Heuristic:** фабрики и шаблонный метод — `static` + LSB; не злоупотреблять `static` состоянием — усложняет тесты. |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | ### 12. Трейты, разрешение конфликтов |
| 85 | |
| 86 | - **Fact:** трейты — горизонтальная композиция; конфликтующие методы — `insteadof`, алиасы `as`. |
| 87 | - **Heuristic:** трейты для пересекающегося поведения, не как «мини-наследование» глубоких иерархий. |
| 88 | |
| 89 | --- |
| 90 | |
| 91 | ### 13. Интерфейсы, перечисления enum (8.1+) |
| 92 | |
| 93 | - **Fact:** интерфейсы описывают контракт; enum — закрытый набор кейсов с опциональными методами; backed enum несёт скаляр. |
| 94 | - **Heuristic:** enum вместо «магических констант» для доменных состояний; сравнение кейсов — идентичность, не значение backed без явного доступа. |
| 95 | |
| 96 | --- |
| 97 | |
| 98 | ### 14. Атрибуты (8.0+) |
| 99 | |
| 100 | - **Fact:** `#[Attr]` метаданные доступны через Reflection; не влияют на рантайм сами по себе без кода, который их читает (фреймворки, тесты). |
| 101 | - **Heuristic:** не дублировать одно и то же в docblock и атрибуте без политики «источник правды». |
| 102 | |
| 103 | --- |
| 104 | |
| 105 | ### 15. `match`, `switch`, nullsafe `?->` |
| 106 | |
| 107 | - **Fact:** `match` сравнивает строго (`===`), без fallthrough; `switch` — loose до указания; `?->` цепочка прерывается на первом null. |
| 108 | - **Heuristic:** предпочитать `match` для перечислений и union-ветвлений; nullsafe не заменяет валидацию домена. |
| 109 | |
| 110 | --- |
| 111 | |
| 112 | ### 16. Иерархия ошибок: Throwable, Error, Exception |
| 113 | |
| 114 | - **Fact:** всё бросаемое реализует `Throwable`; **`Error`** и подтипы — инженерные ошибки (TypeError, ParseError и т.д.), обычно не ловят в бизнес-коде; **`Exception`** — предметные исключения; до PHP 7 многие фаталы были некatchable. |
| 115 | - **Heuristic:** ловить `Throwable` только на верхней границе (логер); в домене — узкие `Exception`; `Error` — чинить код, не маскировать. |
| 116 | |
| 117 | --- |
| 118 | |
| 119 | ### 17. Генераторы, Iterator, ArrayIterator |
| 120 | |
| 121 | - **Fact:** `yield` создаёт генератор; ключи/значения и send/throw — полный протокол; память лучше, чем материализация больших массивов. |
| 122 | - **Heuristic:** не смешивать генератор с повторным проходом без пересоздания; для JSON API больших списков — потоковая запись или чанки. |
| 123 | |
| 124 | --- |
| 125 | |
| 126 | ### 18. Fibers (8.1+) — концепт |
| 127 | |
| 128 | - **Fact:** Fiber — низкоуровневый примитив для приостановки/возобновления стека; удобные async-абстракции строят библиотеки (ReactPHP, Amp и т.д.), не ядро. |
| 129 | - **Heuristic:** без библиотеки не строить production async вручную на Fibers; понимать, что большинство расширений и mysqli блокирующие. |
| 130 | |
| 131 | --- |
| 132 | |
| 133 | ### 19. Пространства имён, use, автозагрузка PSR-4 |
| 134 | |
| 135 | - **Fact:** `namespace` изолирует символы; `use` — алиасы; Composer генерирует автозагрузчик по PSR-4 (путь ↔ namespace prefix). |
| 136 | - **Heuristic:** один класс — один файл; имя класса = имя файла; не полагаться на относительные `include` внутри библиотек. |
| 137 | |
| 138 | --- |
| 139 | |
| 140 | ### 20. Сравнение, равенство, `==` vs `===` |
| 141 | |
| 142 | - **Fact:** `==` приводит типы по таблице приведений (исторически много ловушек); `===` без приведения. |
| 143 | - **Heuristic:** почти везде `===`; для чисел из строк — явная нормализация `filter_var`, `(int)`, `bcmath` для денег. |
| 144 | |
| 145 | --- |
| 146 | |
| 147 | ### 21. Опасные и чувствительные конструкции |
| 148 | |
| 149 | - **Fact:** `eval`, `create_function` (удалена), `assert` с строкой (устарело), `extract`, `parse_str` без второго аргумента, `unserialize` на недоверенных данных — высокий риск (RCE, mass assignment, object injection). |
| 150 | - **Heuristic:** запрет в стандарте кодирования; если `unserialize` неизбежен — `allowed_classes` и доверенный поток. |
| 151 | |
| 152 | --- |
| 153 | |
| 154 | ### 22. Деструкторы, порядок завершения |
| 155 | |
| 156 | - **Fact:** `__destruct` вызывается при уничтожении объекта; порядок при shutdown и циклических ссылках + GC — нетривиален. |
| 157 | - **Heuristic:** не освобождать критичные внешние ресурсы только в деструкторе — использовать явный `close()`/`try-finally`. |
| 158 | |
| 159 | --- |
| 160 | |
| 161 | ## Registry card (template-knowledge-card-v1) |
| 162 | |
| 163 | ### Provenance |
| 164 | - source_refs: `https://www.php.net/manual/en/langref.php`; обобщение семантики 8.x; KB 2026-03-01. |
| 165 | - created_at: 2026-03-01 |
| 166 | - updated_at: 2026-03-01 |
| 167 | |
| 168 | ### Metadata |
| 169 | - card_id: KC-2026-03-01-PHP-LANG-L1 |
| 170 | - world: software.php |
| 171 | - layer: world |
| 172 | - tags: php; semantics; types; oop; errors; namespace |
| 173 | - status: active |
| 174 | |
| 175 | ### Epistemic Linkage |
| 176 | - epistemic_basis: fact + inference |
| 177 | - confidence: high для базовой семантики; medium для edge GC/destructor |
| 178 | - falsification_trigger: расхождение с manual для заявленной версии PHP |
| 179 | |
| 180 | ### Core Unit |
| 181 | - context: проектирование API, отладка TypeError, рефакторинг легаси |
| 182 | - signal: «почему не сравнивается», «почему упал деструктор», «strict_types ломает» |
| 183 | - action: пройти соответствующий §; сверить версию; минимальный reproduce |
| 184 | - lesson: PHP 8.x строже к типам; слабое равенство — ловушка |
| 185 | |
| 186 | ### Operationalization |
| 187 | - first_adoption_task: включить level статанализа на новом коде |
| 188 | - validation_check: тесты граничных типов и сравнений |
| 189 | - success_criterion: предсказуемое поведение на границах |
| 190 | |
| 191 | ### Lifecycle |
| 192 | - supersedes: — |
| 193 | - superseded_by: — |
| 194 | - deprecation_reason: — |
| 195 | |