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

Class not found - причины по убыванию частоты

Страница падает с фатальной ошибкой вида «Class Bitrix\Sale\Order not found» или с именем собственного класса проекта. Разбираем причины по убыванию частоты, начиная с подключения того модуля, которому принадлежит класс.

С чего начать

Смотрим, доступен ли класс автозагрузке:

var_dump(class_exists('\Bitrix\Sale\Order')); // без подключения модуля будет false
var_dump(\Bitrix\Main\Loader::includeModule('sale')); // подключение возвращает признак успеха
var_dump(class_exists('\Bitrix\Sale\Order')); // после подключения класс обязан находиться
// имя класса пишут полностью, вместе с пространством имён и ведущим слэшем

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

Проверяем, установлен ли модуль вообще:

$name = 'sale';
printf("установлен: %s, подключается: %s\n",
\Bitrix\Main\ModuleManager::isModuleInstalled($name) ? 'да' : 'нет',
\Bitrix\Main\Loader::includeModule($name) ? 'да' : 'нет');
// у стороннего решения имя модуля пишут с точкой: vendor.solution

Смотрим регистрацию своих классов:

// include.php своего модуля
\Bitrix\Main\Loader::registerNamespace('Vendor\Module', __DIR__ . '/lib');
// PSR-4: имя файла повторяет имя класса в нижнем регистре
\Bitrix\Main\Loader::registerAutoLoadClasses('vendor.module', ['Vendor\Module\Helper' => 'lib/helper.php']);
// вторая форма - явная карта классов, она нужна для нестандартных путей

Сверяем регистр имени файла:

Окно терминала
ls -la /home/bitrix/www/local/modules/vendor.module/lib/
grep -rn 'namespace\|^class' /home/bitrix/www/local/modules/vendor.module/lib/helper.php
# на боевом сервере регистр важен, а на локальной машине разработчика обычно нет

Причины

  1. Модуль не подключён перед обращением к классу примерно 35% случаев

    ПризнакВ имени класса видно пространство имён платформы: продажи, каталог, инфоблоки.

    ПроверкаПроверяем наличие класса до и после подключения модуля прямо в упавшем файле проекта.

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

  2. Свой класс не зарегистрирован в автозагрузке примерно 25% случаев

    ПризнакОшибка приходит на классе проекта, а файл с этим классом лежит на месте.

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

    Что делатьРегистрируем пространство имён по стандарту либо добавляем класс в явную карту автозагрузки.

  3. Разошёлся регистр имени файла или пространства имён примерно 20% случаев

    ПризнакНа машине разработчика код работает, а на боевом сервере падает с той же строкой.

    ПроверкаСверяем имя файла, имя класса и объявленное в нём пространство имён строго посимвольно.

    Что делатьПриводим имя файла к нижнему регистру, а пространство имён - к пути каталогов.

  4. Не выложена или не подключена папка библиотек примерно 12% случаев

    ПризнакПадает класс сторонней библиотеки, установленной в проект пакетным менеджером.

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

    Что делатьВыкладываем папку библиотек вместе с кодом либо ставим зависимости на самом сервере.

  5. Класс исчез после обновления решения примерно 8% случаев

    ПризнакОшибка появилась сразу после обновления модуля Маркетплейса или ядра платформы.

    ПроверкаИщем имя класса по коду решения и смотрим историю обновлений этого модуля.

    Что делатьПравим вызов под новое имя класса либо откатываем обновление до разбора с автором.

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

Чем эта ошибка отличается от «Call to undefined function»?

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

Нужно ли подключать модуль в каждом файле?

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

Почему на стенде работает, а на сервере нет?

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

Где регистрировать свои классы?

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

Что делать с классами сторонней библиотеки?

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

Смежное

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