Заплатка для вывода элементов с одинаковым символьным кодом
На дворе июль 2016, а некоторые проблемы с ЧПУ так и остаются нерешенными.
В частности, так называемое "дублирование элементов".
А точнее неадекватный выбор элемента компонентом bitrix:catalog.element
в составе комплексного компонента bitrix:catalog в ситуации, когда в разных
разделах каталога есть товары с одинаковыми символьными кодами.
Если таких товаров, например, четыре на весь каталог, то для всех четырех карточек
товара будет отображаться одно и тоже содержимое с тем товаром, который попался
в базе первым из числа этих четырех. Ситуация вовсе не надуманная,
на моей практике встретилась ситуация, когда в одном случае таких
товаров получилось восемь на весь каталог. И на всех восьми урлах одинаковое содержимое.
Т.е. для какого-то одного урла содержимое подходящее, а для остальных семи карточек
оно уже не подходит.
Но, тем не менее, к июлю 2016 в составе продукта уже есть функции, которые позволят
с минимальным программированием внутри шаблонов залатать эту дыру.
Итак, описанную проблему можно решить следующим образом.
Решение приведено для ситуации, когда сначала срабатывает комплексный компонент
bitrix:catalog, и он по шаблону урла (который включает #SECTION_CODE_PATH# и #ELEMENT_CODE#)
адекватно определяет, что это карточка товара и далее вызывает подшаблон element.php
с компонентом bitrix:catalog.element. Вот в этом самом шаблоне element.php комплексного
компонента нужно непосредственно перед самым вызовом компонента bitrix:catalog.element
вставить следующий код:
<?
if($arResult["VARIABLES"]["ELEMENT_ID"] <= 0)
{
$findFilter = array(
"IBLOCK_ID" => $arParams["IBLOCK_ID"],
"IBLOCK_LID" => SITE_ID,
"IBLOCK_ACTIVE" => "Y",
"ACTIVE_DATE" => "Y",
"CHECK_PERMISSIONS" => "Y",
"MIN_PERMISSION" => 'R',
);
if ($arParams['SHOW_DEACTIVATED'] !== "Y")
$findFilter["ACTIVE"] = "Y";
$arResult["VARIABLES"]["SECTION_ID"] = CIBlockFindTools::GetSectionIDByCodePath($arParams["IBLOCK_ID"], $arResult["VARIABLES"]['SECTION_CODE_PATH']);
$arResult["VARIABLES"]["ELEMENT_ID"] = CIBlockFindTools::GetElementID(
$arResult["VARIABLES"]["ELEMENT_ID"],
$arResult["VARIABLES"]["ELEMENT_CODE"],
$arResult["VARIABLES"]["SECTION_ID"],
false,
$findFilter
);
if ($arResult["VARIABLES"]["ELEMENT_ID"] <= 0) {
if (Loader::includeModule('iblock'))
{
\Bitrix\Iblock\Component\Tools::process404(
trim($arParams["MESSAGE_404"]) ?: ''
,true
,$arParams["SET_STATUS_404"] === "Y"
,$arParams["SHOW_404"] === "Y"
,$arParams["FILE_404"]
);
}
return;
}
}
?>
Далее идет штатный вызов компонента bitrix:catalog.element, который оставляется без изменений:
<?$ElementID = $APPLICATION->IncludeComponent(
"bitrix:catalog.element",
?>
Для других ситуаций возможно потребуются правки.
В этой заплатке проблема адекватного поиска нужного элемента
решается дополнительным третьим параметром метода CIBlockFindTools::GetElementID ,
которому передается точный идентификатор раздела SECTION_ID, в котором находится элемент.
А точный идентификатор раздела в свою очередь определяется чудесным методом
CIBlockFindTools::GetSectionIDByCodePath по тому самому пресловутому символьному
пути раздела, возвращаемому от комплексного компонента.
Все это по логике здравого смысла должно происходить внутри компонента bitrix:catalog.element,
которому дополнительно должен передаваться символьный путь раздела. Но там определение
элемента происходит лишь по одному только символьному коду ELEMENT_CODE. Отсюда и проблема.
Дополнительно добавлена отработка 404-й страницы, на случай, если в данном разделе
не найден элемент с таким символьным кодом (например, элемент сделали неактивным,
а из поисковиков по этому урлу по прежнему есть заходы).
Т.к. иначе снова будет задействован поиск элемента внутри bitrix:catalog.element
и снова будет неадекватное определение элемента.
http://dev.1c-bitrix.ru/support/forum/messages/forum6/topic53109/message436245/#message436245