Файл инициализации - порядок подключения, что доступно, ошибки
Разбираемся с файлом инициализации проекта: момент подключения, доступные там данные, состав файла и безопасный порядок правок.
Что нужно знать заранее
Файл инициализации подключается в самом начале обработки любого запроса к сайту. Он выполняется и в публичной части, и в административном разделе, и в консольных скриптах, которые подключают ядро платформы.
На этом раннем этапе сессия ещё не открыта, и текущего пользователя тоже нет. Условия по данным сессии в этом файле не работают, а запускать сессию руками нельзя: это ломает штатный порядок обработки запроса.
Файл своего каталога проекта отменяет одноимённый файл каталога платформы. Работает ровно один из них, и попытка держать оба приводит к тому, что половина обработчиков просто не регистрируется.
Шаги
- Держать файл инициализации в своём каталоге проекта, а не в каталоге платформы.
- Оставить в нём только подключения: автозагрузку классов и файлы обработчиков.
- Не обращаться там к сессии, текущему пользователю и параметрам конкретной страницы.
- Проверять правки на стенде: ошибка в файле роняет сразу весь сайт целиком.
- Держать под рукой способ быстро отключить файл на боевом сайте при аварии.
Решение
Оставляем в файле только подключения:
// /local/php_interface/init.php - выполняется на каждом запросе к сайту\Bitrix\Main\Loader::registerNamespace('Vendor\\Project', __DIR__ . '/../lib/Vendor/Project');require_once __DIR__ . '/events.php'; // регистрация обработчиков событий// тяжёлый код здесь выполняется на каждом запросе, включая запросы к статикеrequire_once __DIR__ . '/helpers.php'; // короткие функции проектаКороткий файл инициализации читается за минуту даже через два года. Прикладная логика живёт в классах, а этот файл лишь объявляет, где её искать платформе.
Регистрируем обработчики отдельным файлом:
// /local/php_interface/events.php - только регистрация, без самой логики$em = \Bitrix\Main\EventManager::getInstance();$em->addEventHandler('sale', 'OnSaleOrderSaved', [\Vendor\Project\OrderHandler::class, 'onSaved']);$em->addEventHandler('iblock', 'OnAfterIBlockElementUpdate', [\Vendor\Project\ElementHandler::class, 'onUpdate']);Список обработчиков в одном файле - самая полезная страница проекта при разборе. Через год именно он отвечает на вопрос, кто и почему меняет данные при сохранении заказа.
Не трогаем сессию и пользователя:
// так делать нельзя: сессии на этом этапе ещё нет// if ($_SESSION['city']) { ... }// правильное место для такой логики - обработчик события пролога страницыAddEventHandler('main', 'OnBeforeProlog', static function () { /* тут сессия уже есть */ });Проверяем, какой именно файл подключается:
\Bitrix\Main\Diag\Debug::writeToFile(__FILE__, date('H:i:s'), 'init.log');// строка в журнале называет файл, который платформа реально подключилаСтрока в журнале снимает вопрос «почему мои обработчики не работают». В половине случаев оказывается, что подключается файл из другого каталога, а правится совсем не он.
Готовим быстрый способ отключить файл:
mv /home/bitrix/www/local/php_interface/init.php /home/bitrix/www/local/php_interface/init.php.offcurl -sI https://example.com/ | head -1 # сайт ожил - причина в этом файлеmv /home/bitrix/www/local/php_interface/init.php.off /home/bitrix/www/local/php_interface/init.phpВозможность отключить файл одной командой стоит дороже красивого кода. Ошибка в нём кладёт и витрину, и административный раздел, а времени на разбор в такой момент обычно нет.
Типичные проблемы
Весь сайт побелел после правки одного файла.
В файле инициализации фатальная ошибка, а он подключается на каждом запросе. Файл временно отключают переименованием и правят ошибку по журналу.
Условие по данным сессии не срабатывает.
Сессия на момент подключения файла ещё не открыта платформой. Такую логику переносят в обработчик события пролога страницы.
Часть обработчиков не регистрируется.
В проекте два файла инициализации, и работает только один из них. Оставляют файл своего каталога, а копию из каталога платформы убирают.
Логика не работает в административном разделе.
Код лежит в файле, привязанном к конкретному сайту, а в админке текущего сайта нет. Общую логику держат в общем файле инициализации проекта.
Файл разросся до тысячи строк и никто его не читает.
В него сложили и регистрацию обработчиков, и саму прикладную логику. Логику выносят в классы, а в файле оставляют только подключения.
Частые вопросы
Когда именно подключается этот файл?
В начале обработки запроса, до открытия сессии и до работы компонентов. Поэтому он влияет на всё: витрину, административный раздел и консольные скрипты.
Можно ли обращаться там к базе данных?
Технически да, но не нужно: запрос выполнится на каждом хите сайта. Данные читают там, где они действительно нужны, и кэшируют.
Где держать функции проекта?
В классах своего пространства имён с автозагрузкой, а не в общем файле. Короткие функции-обёртки допустимы, но их держат отдельным подключаемым файлом.
Чем сайтовый файл отличается от общего?
Он подключается только для своего сайта и не работает в административном разделе. На многосайтовой копии общую логику держат в общем файле.
Как безопасно править этот файл на бою?
Проверять правку на стенде и иметь наготове команду отключения файла. Прямые правки на боевом сайте без проверки роняют сразу всё.
Смежное
-
Настройки и окружение - оглавление подтемы
-
Настройки проекта: файл ядра, опции модуля, разные стенды - где живут значения настроек
-
Обработчик события: регистрация, аргументы, отмена действия - что регистрируют в этом файле
-
Обработчик события не срабатывает: разбор причин - если регистрация не сработала
-
Свой модуль или код в проекте: когда пора выносить в модуль - когда файла уже мало
-
Белая страница вместо сайта: разбор причин - если сайт побелел после правки
-
Ядро D7 - устройство ядра целиком
-
Обработчик срабатывает дважды: разбор причин - чем опасно повторное подключение файла
-
Сайт на технических работах: заглушка и доступ для своих - типовой обработчик на раннем событии