Bitrix

1C-Битрикс — символьный ЧПУ

В стандартной поставке Битрикс есть только один вариант человекопонятных URL — номерные, т.е. мы можем сделать достаточно легко, чтобы ссылка на товар каталога выглядела не так
/catalog/detail.php?ELEMENT_ID=111 , а более приятным образом. Например, вот так /catalog/detail/111/ или как-то еще — все это зависит от нашей фантазии.
Но мы не можем сделать, чтобы ссылка имела вместо цифрового идентификатора 111 , какой-либо символьный, например ice-cream.
Но ведь ссылки вида /catalog/ice-cream/ выглядят явно лучше, чем /catalog/detail/111/ .
Я этой статье я попробую дать решение этой проблемы.

Итак, как же сделать так, чтобы ссылки стали совсем уж дружественными к человеку?

Первая задача — направить ссылки вида /catalog/ice-cream/ на страницу /catalog/detail.php
Для этого придется обратиться к интерфейсу «Настройка правил обработки адресов» ( /bitrix/admin/urlrewrite_list.php?lang=ru ).
Создаем новое правило:
Условие: #^/catalog/([a-zA-Z0-9-]+)/#
Файл: /catalog/detail.php
Правило: ELEM=$1

Можно проверить — это правило будет направлять все подобные ссылки на страницу /catalog/detail.php , но там у нас стоит компонент bitrix:catalog.element, который умеет искать
элементы только по их ID. А мы же предлагаем какой-то символьный код.
Решения таким образом может быть два: либо мы как-то конвертируем код в численный идентификатор, либо переделываем компонент, чтобы он находил элементы по символьному коду.
В каждом из этих случаев нам нужна таблица сопоставления значений символьный код — ID элемента. По моему мнению, проще всего добавить строковое свойство в инфоблок товары.
Назовем его SEF (Search Engine Friendly). И напишем в элемент, который имеет ID 111 в это свойство ice-cream.

Следующая задача — нужно таки преобразовать символьный код в ID код элемента. Проще всего это делать сразу для всех элементов в файле /bitrix/templates/init.php

Примерно так:

RegisterModuleDependences(«main», «OnBeforeProlog», «main», «CMyBot», «StartBuffer», «100»);

class CmyBot
{

function StartBuffer()
{
if (defined(«ADMIN_SECTION») && ADMIN_SECTION===true) return;
define(«MYBOT_IS_ACTIVE», true);
ob_start();

if ($_SERVER[«REAL_FILE_PATH»]==»/catalog/detail.php» && $_REQUEST[«ELEM»]!=»»)
{
$arFilter = Array(«IBLOCK_ID»=>$IBLOCK_ID, «ACTIVE_DATE»=>»Y», «ACTIVE»=>»Y», «PROPERTY_SEF»=>$_REQUEST[«ELEM»]);
$res = CIBlockElement::GetList(Array(), $arFilter, false);
while($ob = $res->GetNextElement())
{
$arFields = $ob->GetFields();
$_REQUEST[«ELEMENT_ID»] = $arFields[«ID»];
}
}
}

function EndBuffer()
{
if(defined(«MYBOT_IS_ACTIVE»))
{
$content = ob_get_contents();
ob_end_clean();

echo $content;
}
}
}

И последняя задача — было бы очень здорово, если бы все ссылки вида /catalog/detail.php?ELEMENT_ID=число автоматически преобразовывались в красивый вид.
Решается это примерно так:

RegisterModuleDependences(«main», «OnAfterEpilog», «main», «CMyBot», «EndBuffer», «100»);
function EndBuffer()
{
if(defined(«MYBOT_IS_ACTIVE»))
{
$content = ob_get_contents();
ob_end_clean();

preg_match_all(«/\/catalog\/detail.php\?.*ELEMENT_ID=([0-9]+)/i», $content, &$matches);
if (count($matches[0]) > 0)
{
$arFilter = Array(«IBLOCK_ID»=>$IBLOCK_ID, «ID»=>$matches[1][$i], «ACTIVE_DATE»=>»Y», «ACTIVE»=>»Y»);
$res = CIBlockElement::GetList(Array(), $arFilter, false);
while($ob = $res->GetNextElement())
{
$arProps = $ob->GetProperties();
}
$arSef[$i] = «/catalog/».$arProps[«SEF»][«VALUE»].»/»;
}
$content = str_replace($matches[0], $arSef, $content);
}

echo $content;
}

Надеюсь, кому-нибудь мои изыскания помогут решить подобную задачу.

Комментариев: 9

  1. В битриксе уже давно есть возможность делать чпу на символьных кодах. При этом не нужно ничего дописывать руками, только настройки инфоблока + настройки компонента.

  2. Возможно я не до конца понял реализации этого метода, но, повторюсь, комплексный компонент каталога (новостей) умеет сам обрабатывать чпу ссылки на кодах.
    К тому же у Вашего метода есть один существенный недостаток — лишние запросы к базе на каждом хите в каталоге. Закешировать бы все это дело:)

  3. Смысл метода в том, что его можно применять для любой структурированной информации. А вы говорите про комплексный компонент новостей. :)

    Кеширование html никто не отменял кстати. Оно абсолютно также будет работать как и для любой другой страницы.

  4. Если есть желание продолжать дискуссию, давайте по e-mail пообщаемся, мне действительно интересно что можно сделать по этому методу и нельзя сделать комплексными новостями)) Пишите, обменяемся опытом.
    А про кеширование — тут в StartBuffer() и EndBuffer() надо бы PHPCache прикрутить, чтобы GetList на каждом хите не отрабатывал.

Оставить комментарий на dvcarrot Отменить

Ваш электронный адрес не будет опубликован.Обязательные для заполнения поля отмечены *

7 + семнадцать =