#Что происходит и когда применима инструкция
При переходе на PHP 8 старый метод, названный как сам класс, больше не считается конструктором. В PHP 5 и части PHP 7 это мог быть способ инициализации объекта. В PHP 8 такой метод остаётся обычным: поля не задаются, родительский конструктор может не вызываться, а последующие действия приводят к ошибкам.
#Причины и диагностические признаки
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Использован конструктор старого стиляИспользован конструктор старого стиля. В классе Legacy есть метод Legacy(), а __construct() отсутствует; после new Legacy() поле не инициализировано. | В классе Legacy есть метод Legacy(), а __construct() отсутствует; после new Legacy() поле не инициализировано. | Перенести создание состояния в __construct(). |
| Сломана иерархия наследованияСломана иерархия наследования. Потомок переопределяет __construct(), но не вызывает parent::__construct(). | Потомок переопределяет __construct(), но не вызывает parent::__construct(). | Явно добавить вызов родительской инициализации, если он нужен. |
| Неправильная версия PHP или иной классНеправильная версия PHP или иной класс. Ошибка появляется только в FPM или при автозагрузке класса другого пространства имён. | Ошибка появляется только в FPM или при автозагрузке класса другого пространства имён. | Проверить версию, фактически загруженный класс и стек вызовов. |
#Подробная пошаговая инструкция
- Проверьте, что проблема действительно появилась после перехода на PHP 8Откройте журнал приложения, запишите первую ошибку и имя класса. Если там TypeError, undefined property или «must not be accessed before initialization», важно понять, где поле должно устанавливаться. Не начинайте заменять все методы с совпадающим именем: часть из них используется как обычные функции.
- Выясните версию обработчика и происхождение классаВ панели сайта посмотрите выбранную версию PHP, а в SSH прочитайте composer.lock либо документацию приложения о поддерживаемых версиях. Класс может находиться в сторонней библиотеке: если это так, ищите совместимый выпуск и не изменяйте vendor вручную.
- SSH, только PHP CLI и синтаксический анализ указанного файлаLinux · Терминал (Bash)КомандаSSH, только PHP CLI и синтаксический анализ указанного файла. Версию веб-FPM проверяйте отдельно; замените путь и бинарник на свои.
php -v; php -l /var/www/example/app/Legacy.php
- Посмотрите имя метода и пространство имёнВ исходнике найдите class Legacy и функцию Legacy(). Для класса из глобального пространства имён этот стиль распознавался до PHP 8, но в новых версиях имя класса уже не означает вызов конструктора. В именованных пространствах имён правило и раньше отличалось; сверяйте фактический класс и версию.
- Сохраните копию класса и создайте воспроизводимый тестВ отдельной тестовой ветке сделайте объект класса с фиктивными данными, не обращаясь к боевому API. Запишите, какие свойства были установлены после new в старой версии, и какой результат получился в PHP 8. Тест должен проверить именно создание объекта, а не всю страницу разом.
- Перенесите инициализацию в __construct с сохранением параметровЕсли Legacy($name) ранее был конструктором, новый public function __construct($name) должен вызывать ту же инициализацию. Не переименовывайте метод автоматически, если код явно вызывает $object->Legacy() как обычную функцию; тогда сохраните совместимый метод-обёртку только по необходимости.
- SSH, только поиск по примеру имени класса Legacy и каталогу app; замените на реальныеLinux · Терминал (Bash)КомандаSSH, только поиск по примеру имени класса Legacy и каталогу app; замените на реальные. Вывод может содержать служебные пути. Искать вручную надёжнее, если используется нестандартная структура.
grep -R -nE "function[[:space:]]+(Legacy|__construct)[[:space:]]*\(" /var/www/example/app
- Проверьте родительский конструктор и типы аргументовЕсли класс наследуется от Base, проверьте, требуется ли вызов parent::__construct(). В PHP он не вызывается автоматически, когда дочерний класс объявил свой __construct. Также проверьте типы свойств и аргументы: PHP 8 может строже проверять передаваемые значения.
- Прогоните тесты и перенесите минимальную правкуВ тестовом окружении проверьте new Legacy() с допустимыми и ошибочными данными, сериализацию, наследование и удаление объекта. Затем осторожно разверните изменения, проверьте прежнюю ошибку и журнал, сохранив способ отката.
- Дополнительная команда по темеLinux · Терминал (Bash)КомандаSSH, только синтаксис исправленного файла для выбранной CLI-версии; успешный результат не заменяет запуск тестов и проверку веб-FPM.
php -l /var/www/example/app/Legacy.php
- Если сайт несовместим целиком, не исправляйте его методом массовой заменыПри большом числе старых расширений безопаснее установить поддерживаемую версию приложения либо провести поэтапную миграцию в тестовой среде. Переход назад на уязвимую старую PHP-ветку в интернет без плана обновления недопустим.
#Как проверить, что проблема исправлена
После создания объекта свойства инициализируются, вызов конструктора родителя происходит там, где требуется, и тесты совместимости проходят на той же версии PHP, что используется сайтом.
#Если не помогло — дальнейшая диагностика и откат
Если метод __construct уже существует, старый метод с именем класса не был выбран конструктором; ищите другую причину. Если проблема только в библиотеке, обновите её совместимым релизом и проверьте зависимости.