Здрасте!
Продолжаем лупить статьи на тему «Битрикс не так уж и плох, если его доработать».
На этот раз разговор пойдет на тему «url_rewrite», потому как я считаю, что текущий вариант вообще не идеален.
А идеальным я считаю вариант маршрутизации в микрофреймворках, например Slim (или тот же Lumen), вообщем тех, которые дружат с PSR-7.
INTRO
На самом деле мои предыдущие статьи носили более менее абстрактный характер (ну кроме статьи про
Кстати про Juggernaut
Документация будет в скором времени, к сожалению есть некоторые преграды:
- время
- рефакторинг
- мне полюбился TDD, так что рефакторинг остановился до тех пор пока не напишу тесты
- направление развитие библиотеки как оказалось я не совсем еще до конца определил
UrlRewrite by Bitrix
Порядок маршрутизации я думаю лучше изобразить схемкой (и понятно, и наглядно):
Что это все значит:
include bitrix/urlRewrite.php
Подключаем файл который занимается маршрутизацией (ну это я думаю и так все поняли).
Вообще данный пункт (и все что выше на блок схеме) — это заслуги .htaccess:
RewriteCond %{REQUEST_FILENAME} !-f # не файл RewriteCond %{REQUEST_FILENAME} !-l # не символьная ссылка RewriteCond %{REQUEST_FILENAME} !-d # не директория RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$ # не файл маршрутизации RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L] |
Данный пункт, судя по комменту в коде, ответственен за какие то косяки IIS (бедняга MS), за какие я не в курсе, но логика следующая:
если QUERY_STRING имеет вид «wtf=404;http(s)://wtf.ru», то все GET параметры запроса чистятся и данная конструкция убирается из адреса.
На вопрос «что проиходит?» я не могу дать ответа, так что едем дальше.
include dbconn.php
Подключаем базу.
Зачем? Непонятно, т. к. запросов к базе дальше нет и работа идет только с файловой системой.
Я конечно не опускался в реализацию классов для работы с файлами, но если им нужно что-либо от базы, то это не иначе как печально
decode request page (for UTF-8 )
Все понятно из названия, кодирование REQUEST_URI.
Зачем? Зачем Битрикс любит Windows-1251? Без понятия. Но это будет продолжаться вечно (и это инсайдерская информация).
include /urlRewrite.php
Собственно подключаем сами правила маршрутизации.
process Url
Немного странные действия, но все же происходит следующее:
Если есть GET параметр SEF_APPLICATION_CUR_PAGE_URL, то приравниваем REQUEST_URI к его значению, а затем переписываем все зависимые переменные и глобальные массивы ($_GET, $_SERVER, …)
process urlRewrite
О, да!
Мы до него добрались.
Собственно что происходит:
- Парсим параметр CONDITION.
- Заменяем параметр CONDITION на RULE в REQUEST_URI
- Добавляет в $_GET и $_REQUEST переменные из правила маршрутизации.
- Проверяем существует ли указанный файл, валидный ли у него путь и не является ли он административным (upload, bitrix, bitrix/services, bitrix/groupdavphp).
- Если все ок, то подключаем.
Много неясностей, зачем сделано так, а не иначе?
Ну и много неясностей, зачем вообще это сделано?
Так что теперь перейдем к идеальному варианту Slim’a.
UrlRewrite by Slim
Как делает этот замечательный фреймворк:
$app = new \Slim\App(); $app->get('catalog/{sectionCode}/{elementCode}/', function(Request $request, Response $response) { // code }); $app->post('catalog/{sectionCode}/{elementCode}/', function(Request $request, Response $response) { // code }); $app->put('catalog/{sectionCode}/{elementCode}/', function(Request $request, Response $response) { // code }); $app->delete('catalog/{sectionCode}/{elementCode}/', function(Request $request, Response $response) { // code }); $app->run(); |
UrlRewrite by Juhhernaut
Ну, а теперь пробуем все это миксануть.
Выкидываем из Slim'a указание метода и собственно реализацию действия, вместо нее будет путь до файла.
Для начала обозначим синтаксис привязки маршрутов к реальным физически файлам (по факту это является мануалом использования):
/* * подключаем файлы для роутрера */ include_once __DIR__.'/modules/olof.juggernaut/includeRewrite.php'; use Jugger\Context\Router; /** * создаем роутер * в отличии от Slim'a маршруты не добавляются, а выполняются * таким образом как только маршрут найден, * остальной код не будет выполняться */ $r = new Router(); /* * поиск файла с комнца маршрута * например, URL запроса выглядит так: "/catalog/section1/section2/element1/", * То поиск поочередно будет перебирать директории в поисках файла 'index.php': * - /catalog/section1/section2/element1/index.php * - /catalog/section1/section2/index.php * - /catalog/section1/index.php * - /catalog/index.php * * в корень сайта опускаться поиск не будет * также никакие параметры не будут добавлены в переменные GET и REQUEST, * т.к. нет шаблона маршрута * данный способ хорошо подходит для стандартной ситуации Битрикс * когда маршрутизация ложится на плечи компонентов */ $r->runRecursive(); /* * добавляем маршрут * формат записи: * {nameParam}, * {nameParam:regExp} * где 'regExp' - регулярное выражение. Например, '\d+' или '[0-9]+' */ $r->run( "/page/", "/page/index1.php" ); $r->run( "/page/{p1:[0-9]+}/{p2}", "/page/index2.php" ); $r->run( "/catalog/", "/catalog/index1.php" ); /* * добавляем сразу несколько маршрутов */ $r->run( [ "/catalog/{sectionCode}/", "/catalog/{sectionCode}/{elementId:\d+}/", ], "/catalog/index2.php" ); /* * маршрутизация в один файл с параметром ?r=path/to/file */ $r->run("{r:.+}", "index.php"); /* * окончание роутига * если никакой маршрут не подошел * то подключается /bitrix/urlrewrite.php */ $r->end(); |
(new Router()) ->runRecursive() ->end(); |
Вместо:
RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$ RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L] |
RewriteCond %{REQUEST_FILENAME} !/local/urlrewrite.php$ RewriteRule ^(.*)$ /local/urlrewrite.php [L] |
Ссылки:
Juggernaut:
Реализация роутера: