1С-Битрикс: ошибка «Элемент не найден» при одинаковом символьном коде раздела и элемента Инфоблока

Рубрики
1С-Битрикс

Симптом проблемы: сайт на 1С-Битрикс, есть каталог с множеством разделов, подразделов и товаров; по какой-то причине некоторые подразделы перестали отображаться — пишет «Элемент не найден». При этом, если перейти по прямой ссылке в какой-нибудь товар этого подраздела, то он нормально отображается.

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

Я не сразу заметил, что общего у всех этих случаев. Оказалось, что в каждом сломавшемся подразделе есть товар с тем же названием, что и этот подраздел. Например, в каталоге растений есть подраздел Мята, а там товары: Мята шоколадная, Мята колосковая, Мята… Вот! Просто Мята — как и название подраздела. Как вы уже догадались, и у подраздела, и у товара сформировался идентичный символьный код — myata.

Отсюда вывод: когда символьный код подраздела и товара совпадают, то у подраздела может появиться ошибка «Элемент не найден».

походу, какой-то баг

Это не штатное поведение — на других сайтах я не замечал такого. Пожалуйста, напишите, в комментариях, если сталкивались с похожей ситуацией и нашли причину.

Способ решения

Как вариант, при обновлении элемента Инфоблока можно проверять, совпадает ли символьный код раздела и элемента. Если совпадает, добавим в символьный код элемента какой-нибудь префикс, например, p_. В таком случае у нашей мяты код стал бы p_myata.

$eventManager->addEventHandler("iblock","OnBeforeIBlockElementUpdate","OnBeforeIBlockElementUpdateHandler"]);

function OnBeforeIBlockElementUpdateHandler(&$arFields)
{
    if ($arFields['IBLOCK_SECTION'][0]>0){
        $arSection = \Bitrix\Iblock\SectionTable::getList([
            'filter'=>[
                'ID'=>$arFields['IBLOCK_SECTION'][0],
            ],
            'select'=>[
                'ID',
                'CODE',
            ],
            'limit'=>1,
        ])->fetch();
        if ($arSection['CODE']==$arFields['CODE']){
            $arFields['CODE'] = 'p_'.$arFields['CODE'];
        }
    }
}

Добавить комментарий