Помогите сформировать регулярку для ЧПУ адресов

danneo

Честный
Регистрация
13 Ноя 2007
Сообщения
1.527
Реакции
121
Есть адрес:
Код:
...?do=search&salesbrand[1]=vaz&salesbrand[2]=nissan_x_trail&salesbrand[3]=lexus&uslugi[1]=moyka&uslugi[2]=polirovka&oplata=nalichka&area[1]=moskva&area[2]=omsk&area[3]=samara&radius_from=[1]&radius_to[2]=18&width_from=185

Нужно его переделать в ЧПУ:
Код:
.../search/salesbrand-vaz-or-nissan_x_trail-or-lexus/uslugi-moyka-or-polirovka/oplata-nalichka/area-moskva-or-omsk-or-samara/radius-from-14-to-18/width-from-185/

Пояснения:
после слеша ставится название переменной. Тире - разделитель. Значения переменно с подчеркиванием или слитно. Если значений несколько, то массив со скобками. Если одно, то без них, типа: &oplata=nalichka.
Если есть два поля (интервалы), например, прайс, то в ЧПУ указывается переменная с суфиксом, например: radius-from-14-to-18. Без ЧПУ это так: &radius_from=[1]&radius_to[2]=18
Если нет начала или окончания интервала, то так: /width-from-185/, без ЧПУ: &width_from=185

Переменные могут быть любые, как присутствовать, так и отсутствовать.

Возможно ли это сделать универсально? Или нужно прописывать для каждой переменной правило?
 
Вот это ты задачку задал :)
Если честно - сложно представить конструкцию, которая бы это дело преобразовывала в ЧПУ средствами htaccess.
Вот на php сварганить обработчик урла - это задача уже вполне реализуемая... Но скорей всего требующая какого-то небольшого финансового вливания...

Хотя тут на форуме есть товарищ lag - возможно он и средствами htaccess сможет задачку решить. С удовольствием бы посмотрел на эту махину...
 
Возможно тебе подойдет подобная реализация
 
RewriteEngine On

RewriteCond $1 ^([^-]+)(?:-from-([^-]+)|-to-([^-]+)){1,2}
RewriteCond %1_from=%2&%3 ^.+(?=&$) [OR]
RewriteCond %1_to=%3&%2 ^.+(?=&$) [OR]
RewriteCond %1_from[1]=%2&%1_to[2]=%3 .+
RewriteRule ^search/([^/]+)(.*) /search$2?%0 [L,QSA]


RewriteCond $1 ^([^-]+)(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?
RewriteCond %1=%2&%3 ^.+(?=&$) [OR]
RewriteCond %1[1]=%2&%1[2]=%3&%1[3]=%4&%1[4]=%5&%1[5]=%6&%1[6]=%7&%1[7]=%8&%1[8]=%9 (&?[^=&]+=[^&]+)+
RewriteRule ^search/([^/]+)(.*) /search$2?%0 [L,QSA]


RewriteRule ^search /index.php?do=$0 [L,QSA]
Исходя из того, что в RewriteCond для сохранения доступно лишь десять переменных %0-%9 и
LimitInternalRecursion если не подкручивать по умолчанию равен 10, то данные правила могут обработать до 9 частей в каждой по 8 элементов разделенных дефисом
/search/first-1-2-3-4-5-6-7-8/second-1-2-3-4-5-6-7-8/
 
Последнее редактирование:
RewriteEngine On

RewriteCond $1 ^([^-]+)(?:-from-([^-]+)|-to-([^-]+)){1,2}
RewriteCond %1_from=%2&%3 ^.+(?=&$) [OR]
RewriteCond %1_to=%3&%2 ^.+(?=&$) [OR]
RewriteCond %1_from[1]=%2&%1_to[2]=%3 .+
RewriteRule ^search/([^/]+)(.*) /search$2?%0 [L,QSA]


RewriteCond $1 ^([^-]+)(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?(?:-([^-]+))?
RewriteCond %1=%2&%3 ^.+(?=&$) [OR]
RewriteCond %1[1]=%2&%1[2]=%3&%1[3]=%4&%1[4]=%5&%1[5]=%6&%1[6]=%7&%1[7]=%8&%1[8]=%9 (&?[^=&]+=[^&]+)+
RewriteRule ^search/([^/]+)(.*) /search$2?%0 [L,QSA]


RewriteRule ^search /index.php?do=$0 [L,QSA]
сложно представить конструкцию
С удовольствием бы посмотрел на эту махину
Спасибо, порадовал.
Примерно такое я и ожидал увидеть в твоём коде... Браво.

PS: заглянул под спойлер "какой-то дикий изврат" - более точно описать содержимое просто невозможно...
 
Исходя из того, что в RewriteCond для сохранения доступно лишь десять переменных %0-%9 и
LimitInternalRecursion если не подкручивать по умолчанию равен 10, то данные правила могут обработать до 9 частей в каждой по 8 элементов разделенных дефисом
/search/first-1-2-3-4-5-6-7-8/second-1-2-3-4-5-6-7-8/
Сказать, что мне мало чего понятно - ничего не сказать :) Это будет работать? И про 10 переменных... Это можно всего 10 фильтров обработать так или 10 параметров у каждого фильтра (типа 10 чекбоксов у каждого фильтра)?

И насколько это адекватный способ по сравнению с PHP обработкой?
 
Получается до 9 фильтров и до 8 параметров в каждом. В принципе можно масштабировать. Сколько требуется фильтров и параметров в фильтрах?

Лучше сделать разбор на php $_SERVER['REQUEST_URI']
 
Получается до 9 фильтров и до 8 параметров в каждом. В принципе можно масштабировать. Сколько требуется фильтров и параметров в фильтрах?

Лучше сделать разбор на php $_SERVER['REQUEST_URI']
Точное кол-во не сказать, но, я так думаю, будет значительно больше фильтров, в разы.
А как делается на php, может кто подсказать, хотя бы механизм?
Я придумал только следующее:
В htaccess нужно передать в файл обработчик (файл модуля)
Код:
RewriteRule ^/search/(.*)$ index.php?act=search&param_filters=$1
После чего на PHP придет в $_GET['param_filters'] = 'salesbrand-vaz-or-nissan_x_trail-or-lexus/uslugi-moyka-or-polirovka/oplata-nalichka'
Далее нужно разбить в массив:
Код:
 $arr_get_param = explode('/', $_GET['param_filters'])
А далее как-то распарсить на название фильтра и его значения.
Думаю, что нужно через foreach разбить каждый элемент массива по знаку "-":
Код:
 explode( "-", $elem_param_massiva )
Первый элемент будет названием поля. Остальное - значения.
Либо разбить каждый элемент на массив по первому вхождению "-". Так в первый элемент попадет название фильтра, во второй - его значения.
А вот как дальше быть, вообще ума не приложу. Как разбить параметры, особенно, если это интервальные значения. То ли разбивать по знаку "-or-", либо по шаблону искать совпадение (если есть from или to), то это интервал, если нет, то это параметры. Если это интервал, то через preg_replace получать переменные. Если это параметры, то через шаблон также получать параметры выборки.
Только проблема в синтаксисе :)
 
Последнее редактирование:
PHP:
$elem_param_massiva = 'radius-from-14-to-18';
//$elem_param_massiva = 'radius-to-18';

if (preg_match('~^([^-]+)(?:-from-([^-]+)|-to-([^-]+)){1,2}~', $elem_param_massiva, $match)) {
// Если диапазон
// $match[1]  Имя
// $match[2]  from
// $match[3]  to
   print_r($match);
   
} else {
// Обычный фильтр
   explode( "-", $elem_param_massiva );
}
 
Назад
Сверху