+7 495 008 8452 пн.-пт. 10:00 – 17:00
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


Подразделы инфоблока в ЧПУ.

Способы включения подразделов инфоблоков в пути для ЧПУ не раз обсуждались и эти способы были разными. В этой статье я хочу описать ещё один способ.

Суть моего решения состоит в том, чтобы до подключения компонента заменять $_SERVER["REQUEST_URI"] на понятный для компонента путь, а затем в result_modifier.php возвращать в $_SERVER["REQUEST_URI"] путь понятный для пользователя, т.е. со всеми подразделами.

Опишу по пунктам, что необходимо сделать, чтобы на сайте заработали правила ЧПУ вида:
#НАЗВАНИЕ_РАЗДЕЛА#/#НАЗВАНИЕ_ПОДРАЗДЕЛОВ#/#НАЗВАНИЕ_ЭЛЕМЕНТА#/

UPD. В последней версии продукта вышла возможность реализовать подобный функционал стандартно, используя в шаблонах ссылок #SECTION_CODE_PATH#


Настройки.
1. В настройках инфоблока указываем:
URL страницы информационного блока: #SITE_DIR#test/
URL страницы раздела: #SITE_DIR#test/#SECTION_CODE#/
URL страницы детального просмотра: #SITE_DIR#test/#ELEMENT_CODE#/
2. В настройках компонента "Каталог" указываем:
Включить поддержку ЧПУ: Да
Каталог ЧПУ (относительно корня сайта): /test/
Раздел: #SECTION_ID#/
Детальная информация: #SECTION_ID#/#ELEMENT_ID#/
Конечно же "test" в обоих случаях необходимо заменить на путь к Вашему разделу.


Код.
1. В файл "/bitrix/php_interface/init.php" вставляем:
<?
class CSubsections
{
   function Init()
   {
      global $APPLICATION;
      
      $sef_folder = (isset($_SERVER["REAL_FILE_PATH"])  &&  $_SERVER["REAL_FILE_PATH"] != "" 
         ?  str_replace("index.php", "", $_SERVER["REAL_FILE_PATH"])
         :  $APPLICATION->GetCurDir(false)
      );
      $uri = $GLOBALS["BACK_REQUEST_URI"] = $APPLICATION->GetCurDir(false);
      $uri = str_replace($sef_folder, "", $uri);
      $uri = trim($uri, "/");
      $tmp_uri = "";

      if($uri  &&  CModule::IncludeModule("iblock")) 
      {
         $rs = CIBlockElement::GetList(
            array(), 
            array("=CODE" => $uri), 
            false, 
            array("nTopCount" => 1), 
            array("ID", "IBLOCK_ID", "IBLOCK_SECTION_ID", "NAME")
         );
         if($ar = $rs->Fetch()) 
         {
            $tmp_uri = $sef_folder.intval($ar["IBLOCK_SECTION_ID"])."/".$ar["ID"]."/";
         }
         else 
         {
            $rs = CIBlockSection::GetList(
               array(), 
               array("=CODE" => $uri), 
               false, 
               array("ID")
            );
            if($ar = $rs->Fetch()) 
            {
               $tmp_uri = $sef_folder.$ar["ID"]."/";
            }
         }
      }
      
      if($tmp_uri)
      {
         $_SERVER["REQUEST_URI"] = $REQUEST_URI = $tmp_uri; 
         $APPLICATION->sDocPath2 = $tmp_uri."index.php";
         CSubsections::InitParser();
      }
      elseif($sef_folder == $APPLICATION->GetCurDir(false))
      {
         CSubsections::InitParser();
      }
   }
   
   function Back($arResult)
   {
      global $APPLICATION;
      
      $arResult["URL_TEMPLATES"]["section"] = "#SECTION_CODE#/";
      $arResult["URL_TEMPLATES"]["element"] = "#ELEMENT_CODE#/";
      $_SERVER["REQUEST_URI"] = $REQUEST_URI = $GLOBALS["BACK_REQUEST_URI"];
      $APPLICATION->sDocPath2 = $GLOBALS["BACK_REQUEST_URI"]."index.php";
      unset($GLOBALS["BACK_REQUEST_URI"]);
   }
   
   function Parse($html)
   {
      $html = str_ireplace("%"."2f", "/", $html);
   }
   
   function InitParser()
   {
      if(!defined("CSUBSECTIONS_INIT_HANDLER"))
      {
         define("CSUBSECTIONS_INIT_HANDLER", true);
         AddEventHandler("main", "OnEndBufferContent", array("CSubsections", "Parse"), 10000);
      }
   }
   
   function GetCode($iblock_id, $section_id, $element_name="")
   {
      $arPath = array();
      
      if(CModule::IncludeModule("iblock"))
      {
         if($element_name)
         {
            $element_name = CUtil::translit($element_name, LANGUAGE_ID);
            $element_name = $element_name?  "/".$element_name:  "";
         }
      
         if($rs = CIBlockSection::GetNavChain($iblock_id, $section_id))
         {
            while($ar = $rs->Fetch()) 
            {
               $arPath[] = CUtil::translit($ar["NAME"], LANGUAGE_ID);
            }
         }
      }
      
      return trim(implode("/", $arPath).$element_name, "/");
   }
   
   function ElementAddHandler($arFields)
   {
      //if($GLOBALS["IBLOCK_ID"] == $IBLOCK_ID)
      //{
         $oElement = new CIBlockElement();
         $oElement->Update($arFields["ID"], array("CODE" => "recalculate"));
      //}
   }
   
   function ElementUpdateHandler($arFields)
   {
      //if($GLOBALS["IBLOCK_ID"] == $IBLOCK_ID)
      //{
         if($rs = CIBlockElement::GetByID($arFields["ID"]))
         {
            if($ar = $rs->Fetch()) 
            {
               $arFields["CODE"] = CSubsections::GetCode(
                  $ar["IBLOCK_ID"], 
                  $ar["IBLOCK_SECTION_ID"],
                  $ar["NAME"]
               );
            }
         }
      //}
   }
   
   function SectionAddHandler($arFields)
   {
      //if($GLOBALS["IBLOCK_ID"] == $IBLOCK_ID)
      //{
         $oSection = new CIBlockSection();
         $oSection->Update($arFields["ID"], array("CODE" => "recalculate"));
      //}
   }
   
   function SectionUpdateHandler($arFields)
   {
      //if($GLOBALS["IBLOCK_ID"] == $IBLOCK_ID)
      //{
         $arFields["CODE"] = CSubsections::GetCode(
            $arFields["IBLOCK_ID"], 
            $arFields["ID"]
         );
      //}
   }
   
   function Recalculate($iblock_id)
   {
      if(CModule::IncludeModule("iblock"))
      {
         $oSection = new CIBlockSection();
         if($rs = CIBlockSection::GetList(array(), array("IBLOCK_ID" => $iblock_id), false, array("ID")))
         {
            while($ar = $rs->Fetch()) 
            {
               $oSection->Update($ar['ID'], array("CODE" => "recalculate"));
            }
         }         
         
         $oElement = new CIBlockElement();
         if($rs = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $iblock_id), false, false, array("ID")))
         {
            while($ar = $rs->Fetch()) 
            {
               $oElement->Update($ar['ID'], array("CODE" => "recalculate"));
            }
         }
      }
   }
}

AddEventHandler("iblock", "OnAfterIBlockElementAdd", array("CSubsections", "ElementAddHandler"));
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate", array("CSubsections", "ElementUpdateHandler"));
AddEventHandler("iblock", "OnAfterIBlockSectionAdd", array("CSubsections", "SectionAddHandler"));
AddEventHandler("iblock", "OnBeforeIBlockSectionUpdate", array("CSubsections", "SectionUpdateHandler"));

CSubsections::InitParser();
?>
2. Перед кодом вызова компонента "Каталог" вставляем:
<?CSubsections::Init();?>
3. В шаблоне компонента "Каталог" создаём(если не создан) файл result_modifier.php (например, в папке "/bitrix/components/bitrix/catalog/templates/.default/" ) с содержимым:
<?CSubsections::Back(&$arResult);?>


Чтобы пересчитать все символьные коды элементов и разделов определённого инфоблока, в "Настройки - Инструменты - Командная PHP-строка" достаточно выполнить код:
CSubsections::Recalculate($IBLOCK_ID);
где $IBLOCK_ID - ID требуемого инфоблока. Стоит учитывать, что если в инфоблоке достаточно много элементов и разделов, то метод может не успеть выполнится до истечения лимита. В этом случае Вам понадобится самостоятельно писать пошаговый скрипт.

В обработчиках изменения/добавления разделов и элементов инфоблока, скорее всего, Вам необходимо будет указать условия выполнения кода для конкретного инфоблока.

Также, обратите внимание на то, что в файле "/bitrix/php_interface/init.php" вызывается метод CSubsections::InitParser(), который инициализирует обработчик события "OnEndBufferContent". Этот обработчик заменяет все "urlencode'нные" ядром символы "/" обратно. Это не совсем правильно, но избавляет от создания многочисленных файлов result_modifier.php для всех компонентов, выводящих ссылки на разделы и элементы, а это все простые компоненты, входящие в состав комплексного компонента "Каталог", компоненты модуля "Поиск" и т.д.

Назад в раздел

Подписаться на новые материалы раздела:












CAPTCHA