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

Тема в разделе "Mod Rewrite / htaccess / ЧПУ", создана пользователем danneo, 9 ноя 2015.

  1. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    Есть адрес:
    Код:
    ...?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

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

    Возможно ли это сделать универсально? Или нужно прописывать для каждой переменной правило?
     
  2. UJy

    UJy

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

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

    javx

    Регистр.:
    28 авг 2015
    Сообщения:
    521
    Симпатии:
    239
    Возможно тебе подойдет подобная реализация
     
  4. lag

    lag

    Регистр.:
    13 окт 2014
    Сообщения:
    188
    Симпатии:
    228
    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/
     
    Последнее редактирование: 10 ноя 2015
    danneo и UJy нравится это.
  5. UJy

    UJy

    Регистр.:
    23 авг 2011
    Сообщения:
    322
    Симпатии:
    117
    Спасибо, порадовал.
    Примерно такое я и ожидал увидеть в твоём коде... Браво.

    PS: заглянул под спойлер "какой-то дикий изврат" - более точно описать содержимое просто невозможно...
     
  6. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    Сказать, что мне мало чего понятно - ничего не сказать :) Это будет работать? И про 10 переменных... Это можно всего 10 фильтров обработать так или 10 параметров у каждого фильтра (типа 10 чекбоксов у каждого фильтра)?

    И насколько это адекватный способ по сравнению с PHP обработкой?
     
  7. lag

    lag

    Регистр.:
    13 окт 2014
    Сообщения:
    188
    Симпатии:
    228
    Получается до 9 фильтров и до 8 параметров в каждом. В принципе можно масштабировать. Сколько требуется фильтров и параметров в фильтрах?

    Лучше сделать разбор на php $_SERVER['REQUEST_URI']
     
  8. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    Точное кол-во не сказать, но, я так думаю, будет значительно больше фильтров, в разы.
    А как делается на 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 получать переменные. Если это параметры, то через шаблон также получать параметры выборки.
    Только проблема в синтаксисе :)
     
    Последнее редактирование: 11 ноя 2015
  9. lag

    lag

    Регистр.:
    13 окт 2014
    Сообщения:
    188
    Симпатии:
    228
    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 );
    }
     
    danneo нравится это.
  10. danneo

    danneo Честный

    Регистр.:
    13 ноя 2007
    Сообщения:
    1.421
    Симпатии:
    109
    у вас мега-мозг в регулярках :)
    Обычный фильтр - это что имеется в виду?