Элементы с одинаковым символьным кодом в Битриксе

В Битриксе далеко не всё так идеально, как это описывают разработчики на конференции. А местами даже откровенно страшно. Но клиентам нравится, что уж тут поделаешь.

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

Проблема эта связана прежде всего с реализацией поиска элемента внутри Битрикса. Суть примерно в этом:

  1. Если ЧПУ выключено или включено, но используется шаблон #ELEMENT_ID#, то идентификатор элемента определяется с помощью GET-параметра или с помощью части адреса, соответствующей этому шаблону. Элемент из инфоблока достаётся по этому идентификатору.
  2. Если ЧПУ включено и используется шаблон #ELEMENT_CODE#, то идентификатор неизвестен, а известен только символьный код (он достаётся из адреса страницы), а далее совершается поиск (внимание!) с использованием: идентификатора инфоблока, идентификатора сайта и символьного кода элемента.

То есть, во втором случае поиск не использует информацию о разделе, что, конечно же, критично. На момент написания статьи актуальна версия 15.5, а проблема всё ещё есть (и тянется как минимум с 2013-го года).

Исправить очень просто. Необходимо перенести компонент bitrix:catalog.element в своё пространство имён (или оставить в bitrix для удобства, но вынести его в /local/components), и в том месте компонента, где определяется идентификатор элемента, добавить в фильтр выборку по коду раздела. На данный момент это 396-я строчка файла component.php:

//Handle case when ELEMENT_CODE used
if($arParams["ELEMENT_ID"] <= 0)
{
	$findFilter = array(
		"IBLOCK_ID" => $arParams["IBLOCK_ID"],
		"IBLOCK_LID" => SITE_ID,
		'SECTION_CODE' => $arParams['SECTION_CODE'], // 396-я строка
		"IBLOCK_ACTIVE" => "Y",
		"ACTIVE_DATE" => "Y",
		"CHECK_PERMISSIONS" => "Y",
		"MIN_PERMISSION" => 'R',
	);
	if ($arParams["SHOW_DEACTIVATED"] !== "Y")
		$findFilter["ACTIVE"] = "Y";

	$arParams["ELEMENT_ID"] = CIBlockFindTools::GetElementID(
		$arParams["ELEMENT_ID"],
		$arParams["ELEMENT_CODE"],
		false,
		false,
		$findFilter
	);
}

Замечу, что это логично использовать тогда, когда у вас в адресе страницы используется код раздела. Иначе, наверное, стоит использовать фильтрацию по его идентификатору.

2015
Популярное