Перейти к содержимому

Файл инициализации - порядок подключения, что доступно, ошибки

Разбираемся с файлом инициализации проекта: момент подключения, доступные там данные, состав файла и безопасный порядок правок.

Что нужно знать заранее

Файл инициализации подключается в самом начале обработки любого запроса к сайту. Он выполняется и в публичной части, и в административном разделе, и в консольных скриптах, которые подключают ядро платформы.

На этом раннем этапе сессия ещё не открыта, и текущего пользователя тоже нет. Условия по данным сессии в этом файле не работают, а запускать сессию руками нельзя: это ломает штатный порядок обработки запроса.

Файл своего каталога проекта отменяет одноимённый файл каталога платформы. Работает ровно один из них, и попытка держать оба приводит к тому, что половина обработчиков просто не регистрируется.

Шаги

  1. Держать файл инициализации в своём каталоге проекта, а не в каталоге платформы.
  2. Оставить в нём только подключения: автозагрузку классов и файлы обработчиков.
  3. Не обращаться там к сессии, текущему пользователю и параметрам конкретной страницы.
  4. Проверять правки на стенде: ошибка в файле роняет сразу весь сайт целиком.
  5. Держать под рукой способ быстро отключить файл на боевом сайте при аварии.

Решение

Оставляем в файле только подключения:

// /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.off
curl -sI https://example.com/ | head -1 # сайт ожил - причина в этом файле
mv /home/bitrix/www/local/php_interface/init.php.off /home/bitrix/www/local/php_interface/init.php

Возможность отключить файл одной командой стоит дороже красивого кода. Ошибка в нём кладёт и витрину, и административный раздел, а времени на разбор в такой момент обычно нет.

Типичные проблемы

Весь сайт побелел после правки одного файла.

В файле инициализации фатальная ошибка, а он подключается на каждом запросе. Файл временно отключают переименованием и правят ошибку по журналу.

Условие по данным сессии не срабатывает.

Сессия на момент подключения файла ещё не открыта платформой. Такую логику переносят в обработчик события пролога страницы.

Часть обработчиков не регистрируется.

В проекте два файла инициализации, и работает только один из них. Оставляют файл своего каталога, а копию из каталога платформы убирают.

Логика не работает в административном разделе.

Код лежит в файле, привязанном к конкретному сайту, а в админке текущего сайта нет. Общую логику держат в общем файле инициализации проекта.

Файл разросся до тысячи строк и никто его не читает.

В него сложили и регистрацию обработчиков, и саму прикладную логику. Логику выносят в классы, а в файле оставляют только подключения.

Частые вопросы

Когда именно подключается этот файл?

В начале обработки запроса, до открытия сессии и до работы компонентов. Поэтому он влияет на всё: витрину, административный раздел и консольные скрипты.

Можно ли обращаться там к базе данных?

Технически да, но не нужно: запрос выполнится на каждом хите сайта. Данные читают там, где они действительно нужны, и кэшируют.

Где держать функции проекта?

В классах своего пространства имён с автозагрузкой, а не в общем файле. Короткие функции-обёртки допустимы, но их держат отдельным подключаемым файлом.

Чем сайтовый файл отличается от общего?

Он подключается только для своего сайта и не работает в административном разделе. На многосайтовой копии общую логику держат в общем файле.

Как безопасно править этот файл на бою?

Проверять правку на стенде и иметь наготове команду отключения файла. Прямые правки на боевом сайте без проверки роняют сразу всё.

Смежное

Первоисточник