freekir
11/30/2016 - 7:02 AM

Заплатка для вывода элементов с одинаковым символьным кодом

Заплатка для вывода элементов с одинаковым символьным кодом

На дворе июль 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