Будем переносить в routes правила для нашего каталога товаров.
/b2b/catalog/index.php - страница инфоблока и страница раздела (страницы списка инфоблоков у нас нет).
/b2b/catalog/test2/ - инфоблок
/b2b/catalog/test2/section/alcohol/ - раздел
/b2b/catalog/detail.php - страница товара
/b2b/catalog/test2/product/whiskey/ - товар
1. Включить механизм routes
.htaccess
В результате ничего не ломается. В конце файла /bitrix/routing_index.php подключается старый /bitrix/urlrewrite.php, совместимость обеспечена.
2. Убираем старые наши правила из urlrewrite
3. Добавить свой новый файл правил в .settings.php
routing -> config - это массив, если уже существует, то в него надо добавить mycatalog.php. Если массив отсутствует, то его надо создать.
4. Наш файл /local/routes/mycatalog.php
Тут нам помогло, что в Битриксе существует много видов параметров для routes. Можно использовать функцию, которая вернёт контент. Можно указать объект-контроллер, который выполнит действие, а можно \Bitrix\Main\Routing\Controllers\PublicPageController в котором единственный параметр - имя файла. Ядро обрабатывает правило, создаёт переменные $_GET и $_REQUEST и выполняет файл, как если бы его вызвали через urlrewrite.
Правило '/b2b/catalog/{IBLOCK_CODE}/' работает для раздела с подразделами вида /b2b/catalog/test/12345. Было бы хорошо иметь шаблон с $ на конце, типа '/b2b/catalog/{IBLOCK_CODE}/$', чтобы для вложенных разделов автоматически была 404 страница, но так не работает.
Я не нашёл нигде как сделать, чтобы правило работало только для указанной страницы, кроме как сделать другое правило для вложенных страниц на страницу '/b2b/catalog/404_routes.php'. Пример: '/b2b/catalog/{IBLOCK_CODE}/{END_PATH}'
Битрикс ищет шаблоны {ELEMENT_CODE}, {SECTION_CODE}, {IBLOCK_CODE} по регулярному выражению: '[^/]+' , для {END_PATH} мы указываем правило where('END_PATH', '.*');, чтобы искать по регулярному выражению '.*'
Еще приходится создать страницу /b2b/catalog/404_routes.php вместо стандартной.
5. Страница /b2b/catalog/index.php
Мы можем использовать переменные $_REQUEST["IBLOCK_CODE"], $_REQUEST["SECTION_CODE"], $_REQUEST["IBLOCK_CODE"] как и раньше.
Но теперь у нас есть объект роута с параметрами.
Мы выше задавали имя роута - это тип страницы, с помощью этого параметра тоже можно определять страницу, на которую мы пришли
(традиционно проверку тоже делать можно через $_REQUEST["IBLOCK_CODE"] и $_REQUEST["SECTION_CODE"] )
Итого: каких-то серьёзных проблем в переходе с urlrewrite на роутинг нет. Роутинг можно использовать для обычных страниц.
Ещё роутинг можно использовать для возвращения контента через API или через контроллеры. Роутинг можно обновлять автоматически, если выпустить модуль в маркетплейс со своими правилами обработки url.
Но каких-то очевидных преимуществ перед старым способом тоже не видно.
/b2b/catalog/index.php - страница инфоблока и страница раздела (страницы списка инфоблоков у нас нет).
/b2b/catalog/test2/ - инфоблок
/b2b/catalog/test2/section/alcohol/ - раздел
/b2b/catalog/detail.php - страница товара
/b2b/catalog/test2/product/whiskey/ - товар
1. Включить механизм routes
.htaccess
#RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
#RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
RewriteCond %{REQUEST_FILENAME} !/bitrix/routing_index.php$
RewriteRule ^(.*)$ /bitrix/routing_index.php [L] |
2. Убираем старые наши правила из urlrewrite
Правила urlrewrite 6 => array ( 'CONDITION' => '#^/b2b/catalog/([^/]+)/product/([^/]+)/([^/]*)#', 'RULE' => 'IBLOCK_CODE=$1&ELEMENT_CODE=$2', 'ID' => '', 'PATH' => '/b2b/catalog/detail.php', 'SORT' => 100, ), 4 => array ( 'CONDITION' => '#^/b2b/catalog/([^/]+)/section/([^/]+)/([^/]*)#', 'RULE' => 'IBLOCK_CODE=$1&SECTION_CODE=$2', 'ID' => '', 'PATH' => '/b2b/catalog/index.php', 'SORT' => 100, ), 5 => array ( 'CONDITION' => '#^/b2b/catalog/([^/]+)/([^/]*)#', 'RULE' => 'IBLOCK_CODE=$1', 'ID' => '', 'PATH' => '/b2b/catalog/index.php', 'SORT' => 100, ), |
3. Добавить свой новый файл правил в .settings.php
'routing' => ['value' => [ 'config' => ['mycatalog.php'] ]], |
4. Наш файл /local/routes/mycatalog.php
<?php
return function (Bitrix\Main\Routing\RoutingConfigurator $routes)
{
$routes->any('/b2b/catalog/{IBLOCK_CODE}/product/{ELEMENT_CODE}/',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/detail.php'),
)->name("mycatalog.element");
$routes->any('/b2b/catalog/{IBLOCK_CODE}/section/{SECTION_CODE}/',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/index.php'),
)->name("mycatalog.section");
$routes->any('/b2b/catalog/{IBLOCK_CODE}/',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/index.php'),
)->name("mycatalog.iblock");
$routes->any('/b2b/catalog/{IBLOCK_CODE}/product/{ELEMENT_CODE}/{END_PATH}',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/404_routes.php'),
)->where('END_PATH', '.*');
$routes->any('/b2b/catalog/{IBLOCK_CODE}/section/{SECTION_CODE}/{END_PATH}',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/404_routes.php'),
)->where('END_PATH', '.*');
$routes->any('/b2b/catalog/{IBLOCK_CODE}/{END_PATH}',
new \Bitrix\Main\Routing\Controllers\PublicPageController('/b2b/catalog/404_routes.php'),
)->where('END_PATH', '.*');
};
|
Тут нам помогло, что в Битриксе существует много видов параметров для routes. Можно использовать функцию, которая вернёт контент. Можно указать объект-контроллер, который выполнит действие, а можно \Bitrix\Main\Routing\Controllers\PublicPageController в котором единственный параметр - имя файла. Ядро обрабатывает правило, создаёт переменные $_GET и $_REQUEST и выполняет файл, как если бы его вызвали через urlrewrite.
Правило '/b2b/catalog/{IBLOCK_CODE}/' работает для раздела с подразделами вида /b2b/catalog/test/12345. Было бы хорошо иметь шаблон с $ на конце, типа '/b2b/catalog/{IBLOCK_CODE}/$', чтобы для вложенных разделов автоматически была 404 страница, но так не работает.
Я не нашёл нигде как сделать, чтобы правило работало только для указанной страницы, кроме как сделать другое правило для вложенных страниц на страницу '/b2b/catalog/404_routes.php'. Пример: '/b2b/catalog/{IBLOCK_CODE}/{END_PATH}'
Битрикс ищет шаблоны {ELEMENT_CODE}, {SECTION_CODE}, {IBLOCK_CODE} по регулярному выражению: '[^/]+' , для {END_PATH} мы указываем правило where('END_PATH', '.*');, чтобы искать по регулярному выражению '.*'
Еще приходится создать страницу /b2b/catalog/404_routes.php вместо стандартной.
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Страница не найдена");
CHTTP::SetStatus("404 Not Found");
@define("ERROR_404","Y");
?>
Извините, страница не найдена
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?> |
5. Страница /b2b/catalog/index.php
Мы можем использовать переменные $_REQUEST["IBLOCK_CODE"], $_REQUEST["SECTION_CODE"], $_REQUEST["IBLOCK_CODE"] как и раньше.
Но теперь у нас есть объект роута с параметрами.
Мы выше задавали имя роута - это тип страницы, с помощью этого параметра тоже можно определять страницу, на которую мы пришли
(традиционно проверку тоже делать можно через $_REQUEST["IBLOCK_CODE"] и $_REQUEST["SECTION_CODE"] )
/// страница /b2b/catalog/index.php
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Каталог");
?>
<?
$currentRoute = \Bitrix\Main\Application::getInstance()->getCurrentRoute();
if ( $currentRoute->getOptions()->getFullName() === "mycatalog.iblock" )
{
echo "<br>Инфоблок: ".$_REQUEST["IBLOCK_CODE"];
}
elseif($currentRoute->getOptions()->getFullName() === "mycatalog.section")
{
echo "<br>Инфоблок: ".$_REQUEST["IBLOCK_CODE"];
echo "<br>Раздел: ".$_REQUEST["SECTION_CODE"];
}
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?> |
Итого: каких-то серьёзных проблем в переходе с urlrewrite на роутинг нет. Роутинг можно использовать для обычных страниц.
Ещё роутинг можно использовать для возвращения контента через API или через контроллеры. Роутинг можно обновлять автоматически, если выпустить модуль в маркетплейс со своими правилами обработки url.
Но каких-то очевидных преимуществ перед старым способом тоже не видно.