Исправление ошибки «Cannot instantiate abstract class Bitrix\Iblock\Component\Base»
19 февраля 2023
После обновления PHP на версию 7.4 в старых версиях Битрикса возникает ошибка вида Cannot instantiate abstract class Bitrix\Iblock\Component\Base. Это происходит из-за того, что в PHP у функции get_declared_classes (https://www.php.net/manual/en/function.get-declared-classes.php) изменился порядок возвращаемых классов — теперь строгость следования родительских классов не гарантируется.
Для решения проблемы нужно подредактировать файл /bitrix/modules/main/classes/general/component.php (перед внесением правок обязательно сделайте резервную копию файла).
добавляем вот этот код:
на следующий код:
Готово, ошибка должна уйти
Для решения проблемы нужно подредактировать файл /bitrix/modules/main/classes/general/component.php (перед внесением правок обязательно сделайте резервную копию файла).
ШАГ 1
После фрагмента:private static $__classes_map = array();
добавляем вот этот код:
private static $classes = array();
ШАГ 2
Затем необходимо изменить определение метода __getClassForPath. Заменяем фрагмент:final private function __getClassForPath($componentPath)
{
if (!isset(self::$__classes_map[$componentPath]))
{
$fname = $_SERVER["DOCUMENT_ROOT"].$componentPath."/class.php";
if (file_exists($fname) && is_file($fname))
{
$beforeClasses = get_declared_classes();
$beforeClassesCount = count($beforeClasses);
include_once($fname);
$afterClasses = get_declared_classes();
$afterClassesCount = count($afterClasses);
for ($i = $beforeClassesCount; $i < $afterClassesCount; $i++)
{
if (is_subclass_of($afterClasses[$i], "cbitrixcomponent"))
self::$__classes_map[$componentPath] = $afterClasses[$i];
}
}
else
{
self::$__classes_map[$componentPath] = "";
}
}
return self::$__classes_map[$componentPath];
}
на следующий код:
final private function __getClassForPath($componentPath)
{
if (!isset(self::$__classes_map[$componentPath]))
{
$fname = $_SERVER["DOCUMENT_ROOT"].$componentPath."/class.php";
if (file_exists($fname) && is_file($fname))
{
$beforeClasses = get_declared_classes();
$beforeClassesCount = count($beforeClasses);
include_once($fname);
$afterClasses = get_declared_classes();
$afterClassesCount = count($afterClasses);
for ($i = $beforeClassesCount; $i < $afterClassesCount; $i++)
{
if (!isset(self::$classes[$afterClasses[$i]]) && is_subclass_of($afterClasses[$i], "cbitrixcomponent"))
{
if (!isset(self::$__classes_map[$componentPath]) || is_subclass_of($afterClasses[$i], self::$__classes_map[$componentPath]))
{
self::$__classes_map[$componentPath] = $afterClasses[$i];
//recursion control
self::$classes[$afterClasses[$i]] = true;
}
}
}
}
else
{
self::$__classes_map[$componentPath] = "";
}
}
return self::$__classes_map[$componentPath];
}
Готово, ошибка должна уйти