За последние 24 часа нас посетил 21781 программист и 1332 робота. Сейчас ищут 719 программистов ...

Построение регулярных выражений для отображения ЧПУ (friendly url) через .htaccess

Тема в разделе "Настройка веб-сервера", создана пользователем Programmed, 23 апр 2024.

  1. Programmed

    Programmed Новичок

    С нами с:
    22 апр 2024
    Сообщения:
    2
    Симпатии:
    0
    Привет всем разработчикам!

    Пытаюсь построить регулярное выражение для отображения ЧПУ (friendly url) на сайте.

    Сейчас в адресной строке у меня примерно вот что:

    http://python4all.ru/index.php?option=com_erp&plugin=goods&act=showitem&id=3&en_name=basic_python

    А нужно, чтоб было:

    http://python4all.ru/basic_python

    Я добавил в .htaccess регулярное выражение вида:
    Код (Text):
    1. RewriteRule ^([a-z0-9\-\_]+)/([a-z0-9\-\_]+)/$ ?option=com_erp&plugin=goods&act=showitem&id=$1&en_name=$2 [L]
    Но оно не сработало. Что сделано не так?
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    в поисковик: php единая точка ЧПУ
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Давай ты расскажешь о задаче, а не о предполагаемом решении. Что-то сомневаюсь что тебе не нужно разбирать параметры командной строки в .htaccess.

    Есть варианты:
    1. сайт уже работает с "красивыми" адресами типа как во второй строке, но существующие ссылки содержат старые адреса с параметрами.
    2. сайт понимает ссылки первого типа, а хочется ничего не исправляя в коде (лол!) принимать "красивые" URL

    Решение зависит от цели, очевидно. И таки что надо?
     
  4. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.795
    Симпатии:
    650
    «Единая точка входа», как выше написали. Начальные слаги можно хранить в коде или в БД. В БД можно так.
    --- Добавлено ---
    Mля. По ссылке в старт. посте сайт на тильде. В тильде разучились делать ЧПУ или какого х-ра?!
    --- Добавлено ---
    В подобных правилах файл-обработчик лучше всегда писать явно, чтобы не было доп. скрытого рерайта. Черточка в множествах из регулярок не так делается. Просто добавь ее в конец множества без какого-либо экранирования: [a-z0-9_-]
     
  5. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    В БД хранятся ЧПУ слаги для кастомизации с панели управления. Но, на сервере должен создаваться кэш выгруженный слагов для быстродействия и сведению к минимум обращений в БД
     
  6. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Маршрут по-умолчанию считает страницу ЧПУ-шкой. Остальные маршруты регистрируются ДО маршрута по-умолчанию. Если человек введет что-то, что система знает - попадет на привязанную страницу. Если ничего не отработает - дефолтный маршрут распознает ЧПУ. Если хочется скорости, то маршрут удобно заканчивать на ID, примерно как "my/custom/link--1", тогда все обращения к сайту, которые заканчиваются на два минуса и цифру - это ЧПУ. Пост при этом можно искать по самой цифре, а найдя его - построить ЧПУ чтобы принудительно сделать редирект. Тестирование получается вкуснейшее - пишем в браузере site.ru/--2 и нас перекидывает на site.ru/my-page--2/
     
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    К производительности это не имеет никакого отношения. Любой урл запрос проходит через регулярную валидацию с множествами опциями. Не имеет никакого отношения что будет стоять ID или буква. Весь урл сверяется с map картой по первому найденному с GET/POST/HEAD и т.д. параметрами. Ваше предложение явно несет информацию со времен нулевых годов, которую до сих пор динозавры копируют друг у друга и делают себе контент, а вы смотрите, осваиваете и не задаетесь вопросом "а правильно ли это ?"
     
  8. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Я могу тебе помочь с задачами если у тебя был тяжелый денек.

    Я просто уверен, что регулярка '/--[0-9]+$/' сработает сильно быстрее на большом числе входящих запросов, чем "сначала проверить все другие страницы регулярками", а потом отработать ЧПУ как "дефолт".
     
  9. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Но безусловно, если речь о регулярке на уровне .htaccess или nginx, то конечно, там механизмы свои, но порядок все равно важен.
    Я просто сторонник того что регулярки должны быть в том месте, которое я спокойно пушу не в докерхаб, а все таки в гит. Чтобы программисты могли за этим следить, а не бегать по кабинетам и искать девопса.
     
  10. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    Бред. В цикле роутер будет пробегать каждый раз по списку и сверять каждый слаг из мапы и не важно где будет стоять твоё '/--[0-9]+$/'. Будет произведен последовательный поиск, а не "Я просто уверен". Я не буду говорить и поддерживать речь об втюхивание ЧПУ в .htaccess или nginx.
     
  11. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Суперстар настолько зол на мир, что предпочитает в лицо изрыгнуть злобу.
    Не будешь поддерживать - тебя просили, мурло?
    Ты хочешь форум в сральню превратить?

    Скажи вежливо "я считаю что, потому что, думаю вы ошибаетесь". Нет ты провоцируешь на гнев, а чел и я вынуждены это читать, и ты за экранчиком и тебе посрать. Иди посри, если посрать.

    Я грю в роутере, написанном на пыхе который обходит циклом через foreach() если первый роут написан как "--цифра" то он отработает первый, остальные запущены не будут.

    Но если ты эксперт в серверах или nginx-ах, и знаешь как там работает MAP - флаг тебе в руки. Я знаю как работает форич, и чем быстрее ты его закончишь тем быстрее вернется результат. И double-linked-list для поиска по ключу вместо in_array() мне тоже известен.

    Но блин, я забыл, тебе же посрать.

    Ушел из чатов, потому что там дибилоиды котиков перепосчивают друг другу, пришел на борду, а тут из ведра дерьмом поливают. Люди, вы ебнулись?
     
  12. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
  13. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Первая встреча с представителем местной фауны. Вердикт - свинья.
    --- Добавлено ---
    Роутер выглядит вот так.
    А это у тебя что-то в голове из интернет-курсов затерялось.

    Возвели Симфони тотэм и так моляться, что все вокруг приходящие обязаны тоже вонять. Я симфони уже лет 6 не использую.

    Код (Text):
    1.  public function match($filter) : array
    2.     {
    3.         $filterNames = (array) ($filter->names ?? $filter->name ?? null);
    4.         $filterMethods = (array) ($filter->methods ?? $filter->method ?? null);
    5.         $filterGroups = (array) ($filter->groups ?? $filter->group ?? null);
    6.         $filterPath = $filter->path ?? '';
    7.  
    8.         $compiled = $this->compileRoutes();
    9.  
    10.         $intersect = [];
    11.  
    12.         $intersect[] = array_keys($compiled);
    13.  
    14.         foreach ( $filterNames as $filterName ) {
    15.             $intersect[] = array_keys($this->routesCompiledByName[ $filterName ] ?? []);
    16.         }
    17.  
    18.         foreach ( $filterMethods as $filterMethod ) {
    19.             $intersect[] = array_keys($this->routesCompiledByMethod[ $filterMethod ] ?? []);
    20.         }
    21.  
    22.         foreach ( $filterGroups as $filterGroup ) {
    23.             $intersect[] = array_keys($this->routesCompiledByGroup[ $filterGroup ] ?? []);
    24.         }
    25.  
    26.         $attributes = [];
    27.         if ($filterPath) {
    28.             reset($this->routesCompiledByRegex);
    29.  
    30.             while ( null !== ($regex = key($this->routesCompiledByRegex)) ) {
    31.                 if (preg_match('/' . $regex . '/', $filterPath, $m)) {
    32.                     $intersect[] = array_keys($this->routesCompiledByRegex[ $regex ]);
    33.  
    34.                     foreach ( $m as $key => $value ) {
    35.                         if (is_string($key)) {
    36.                             $attributes[ $key ] = $value;
    37.                         }
    38.                     }
    39.  
    40.                     break;
    41.                 }
    42.  
    43.                 next($this->routesCompiledByRegex);
    44.             }
    45.         }
    46.  
    47.         $routesCompiledMatch = array_intersect(...$intersect);
    48.  
    49.         if ($routesCompiledMatch) {
    50.             $routesCompiledMatch = array_intersect_key(
    51.                 $this->routesCompiled,
    52.                 array_flip($routesCompiledMatch)
    53.             );
    54.         }
    55.  
    56.         if ($attributes) {
    57.             foreach ( $routesCompiledMatch as $routeCompiled ) {
    58.                 reset($routeCompiled->actionAttributes);
    59.  
    60.                 while ( null !== ($key = key($routeCompiled->actionAttributes)) ) {
    61.                     $routeCompiled->actionAttributes[ $key ] = $attributes[ $key ] ?? null;
    62.  
    63.                     next($routeCompiled->actionAttributes);
    64.                 }
    65.             }
    66.         }
    67.  
    68.         return $routesCompiledMatch;
    69.     }
     
  14. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    Если твой слаг стоит в карте на первом месте, то он и ОТРАБОТАЕТ первым, а если он стоит на последнем месте, то он отработает ПОСЛЕ всех остальных слагов по верификации.
    --- Добавлено ---
    Конечно, лучше юзать код какого-то васи.
     
  15. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    Ну, звучит умно.

    Я не понял откуда карта?
    Есть список роутов, они в массиве лежат, пробегаешься по роутам - у каждого регулярка.
    Чем раньше отсечешь свою тем быстрее отработает.

    На нагрузке в 5 человек плевать. На нагрузке в косарь-полтора людей щелкающих кнопки на сайте - чувствуется.
    --- Добавлено ---
    Да, этот Вася, я точнее, написал себе Доктрину строк в 500 кода. А не Васи постят друг другу мемчики и пользуются дредноутом на 500 классов. Ради того чтобы получить структуру данных очередь и сохранение рекурсией по графу. Всей планетой долбятся! Я переписал наверное за жизнь половину симфонийских пакетов, и знаю что они внутри такое.
     
  16. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    871
    Симпатии:
    135
    @gzhegow откуда вылез? форки покажи пакетов, или сам в себя переписал?
     
  17. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.795
    Симпатии:
    650
    Избыточный числовой id в адресе – уже не очень. Такое можно практиковать только в меганагруженных проектах. Причем там можно оставить только числовые id без избыточности.

    Одна коллекция на весь сайт? Или речь о том, чтобы для др. коллекции писать /col-2/--2?
    --- Добавлено ---
    Вообще нафиг такие дубли, даже с автоправкой редиректом.
     
  18. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.764
    Симпатии:
    1.322
    Адрес:
    Лень
    Поэтому ты в своем коде юзаешь 17 циклических операций на роутер, 7 из которых - на каждый слаг ЧПУ ? Да еще успеваешь чепуху про 500 классов сочинить и об страшной нагрузки которой сам никогда не видел. Чувак, изучи PHP 8, где скомпилированный код при нагрузке можно кешировать в память и будет плевать сколько ты там классов родил. Вспомнил одного новичка недавнего про PHPDoc, который composer не хотел юзать, потому что ТАМ 100500 ФАЙЛОВ !!11!... Вот это мем, нет, это религиозная боязнь "чего-то незнакомого", и ты @gzhegow к сожалению только что мне на3.14здил, что ты там чего-то переписывал от симфони.
    Я лично в свое свободное время написал роутер с доп опциями атрибутов и знаешь что ? Я тупо потратил время в пустую. Написанный код был фактически такой же как в симфони.

    Теперь так же в пустую время трачу на Васю, который преувеличивает свой опыт и выходит с рамки конструктивного диалога - САМООСКОРБЛЕНИЕ.
    --- Добавлено ---
    PHP:
    1.    "register": {
    2.         "edit": true,
    3.         "active": false,
    4.         "route": {
    5.             "path": "/registration",
    6.             "controller": {
    7.                 "_controller": [
    8.                     "Auth",
    9.                     "register"
    10.                 ]
    11.             },
    12.             "methods": [
    13.                 "GET",
    14.                 "POST"
    15.             ],
    16.             "requirements": [],
    17.             "options": [],
    18.             "host": null,
    19.             "schemes": [],
    20.             "condition": null,
    21.             "defaults": [],
    22.             "priority": 0
    23.         }
    24.     },
    25.     "account-activation": {
    26.         "edit": true,
    27.         "active": false,
    28.         "route": {
    29.             "path": "/confirm-account",
    30.             "controller": {
    31.                 "_controller": [
    32.                     "Auth",
    33.                     "activation"
    34.                 ]
    35.             },
    36.             "methods": [
    37.                 "GET"
    38.             ],
    39.             "requirements": [],
    40.             "options": [],
    41.             "host": null,
    42.             "schemes": [],
    43.             "condition": null,
    44.             "defaults": [],
    45.             "priority": 0
    46.         }
    47.     },
    48.     "login": {
    49.         "edit": true,
    50.         "active": true,
    51.         "route": {
    52.             "path": "/login",
    53.             "controller": {
    54.                 "_controller": [
    55.                     "Auth",
    56.                     "login"
    57.                 ]
    58.             },
    59.             "methods": [
    60.                 "GET",
    61.                 "POST"
    62.             ],
    63.             "requirements": [],
    64.             "options": [],
    65.             "host": null,
    66.             "schemes": [],
    67.             "condition": null,
    68.             "defaults": [],
    69.             "priority": 0
    70.         }
    71.     },
    72.     "logout": {
    73.         "edit": true,
    74.         "active": true,
    75.         "route": {
    76.             "path": "/logout",
    77.             "controller": {
    78.                 "_controller": [
    79.                     "Auth",
    80.                     "logout"
    81.                 ]
    82.             },
    83.             "methods": [
    84.                 "GET"
    85.             ],
    86.             "requirements": [],
    87.             "options": [],
    88.             "host": null,
    89.             "schemes": [],
    90.             "condition": null,
    91.             "defaults": [],
    92.             "priority": 0
    93.         }
    94.     },
     
  19. gzhegow

    gzhegow Новичок

    С нами с:
    28 апр 2024
    Сообщения:
    7
    Симпатии:
    0
    чтобы ответ за базар требовать заслужи уважение. ты не захочешь. и я тоже. найди меня в телеге, я тебе скажу какой и зачем переписывал и в чем дело. а байтить меня, чтобы я тут сейчас защищался перед "всеми" - выдыхай.

    @miketomlin ты очень верно заметил, что лучше иметь несколько коллекций чем одну, и подключать разную коллекцию на разной точке входа, которая срабатывает из апача или nginx изначально, чтобы сделать еще быстрее. Но думаю, что для ЧПУ будет использоваться дефолтная коллекция, т.к. она про содержимое сайта и наиболее короткий УРЛ который только возможен. и в этом случае первым роутом зарегистрировать регуляркку "~[-][-][0-9]+$~, которая сделает считай strrpos(), и сразу поймет - это ЧПУ или нет - мне кажется это разумнее, чем заставлять её парсить "неопределенное количество наклонных слешей между которыми любое количество не-слешей". Так сразу понятно - "заначивается на два дефиса и цифру? - отправлять в контроллер постов".

    На практике там не будет дубляжа, потому что если роут строить для карты сайта - он будет полный. А вот входить можно только по концовке. То есть поисковик будет видеть полные урлы, а работать будет лайфхаком.

    --- Добавлено ---
    Больше не трать пожалуйста свое ультраценное время, потому что я не могу слушать собеседника, который целью считает показать другому, что тот днище. Имей ты желание указать мне и помочь исправить мои ошибки, ты бы вёл себя иначе. Можешь быть каким хочешь, ты не обязан. Но и я общаться с тобой не обязан тоже. По мне - цель общения найти помощников и новых знакомых. Но если им тыкать, что они дно - ничего не выйдет. Значит твоя цель точно не в этом. И я не могу придумать другой, как не показать всем что-то. А значит, ни диалог, ни монолог ничего не дадут, на все возмущения найдется аргумент, на все корректировки - оскорбление. И это и вправду лишняя трата времени, для нас обоих.
     
  20. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    871
    Симпатии:
    135
    @gzhegow, я задал вопрос исходя из твоего утверждения, всего-то, защиты не требую.