За последние 24 часа нас посетили 18348 программистов и 1634 робота. Сейчас ищут 1532 программиста ...

Реализация произвольных ЧПУ. [Рассуждение, поиск алгоритма]

Тема в разделе "Решения, алгоритмы", создана пользователем Koc, 1 мар 2009.

  1. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    это относительно просто. Так не интересно и не всегда хорошо. Смотри первый пост этого треда.
     
  2. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Самым последним в списке ставим:

    RewriteRule ^(.+)[/]*$ index.php?do=$1 [L]

    А дальше парсим URL.
    Раз под выше-написанные правила не подходит, будет обработана именно эта строка.
    При парсировании определять.
     
  3. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    приведи пример, а я попробую решить его посвоему =)
    Зы. По крайней мере, в моём случае твоя проблема решается элементарно ;)
     
  4. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Mr.M.I.T.
    примера пока нет. Разве что просто хочется максимальной гибкости.
    Хотя я согласен, что проблему можно решить проще, используя /модуль/действие/параметры

    Apple
    сорри, поподробней. То есть ты предлагаешь часть делать под ЧПУ, а часть под ?m=cat&id=4 ?
     
  5. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Koc
    Я предлагаю те URL, которые не подходят под запрос (тобиш все, как видно по регулярнке) перехватывать и вручную парсировать.
    Мы перехватываем ЛЮБЫЕ адреса, вне зависимости от указания категории или чего-то ещё.
    Мы полностью перехватываем строку и уже со стороны РНР вручную разбираем, определяя уровень вложенности у требуемое действие.
    Довольно хлопотно, конечно.

    Но зато адреса будут не фиксированы - это раз, во-вторых мы будем иметь над ними полнейший контроль.


    ПыСы:
    Отличается от Query_URI тем, что мы разрешаем адреса вида /abc/def/abc/mui.html
     
  6. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Koc
    ну дык, и чем твой вариант гипче будет? =) ну да ладно дело твоё, сам может потом поймёшь как лучше
    и кстати, ещё можно так
    av/tv/?filter=sumsung
     
  7. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    о! нужно будет попробовать это.
     
  8. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Эх..

    есть урл: http://site.com/example/show/1.html
    Код (Text):
    1.  
    2. # .htaccess
    3. Options -Indexes
    4.  
    5. php_value magic_quotes_gpc off
    6. php_value register_globals off
    7.  
    8. <FilesMatch  "\.(inc)$">
    9. Order Deny,Allow
    10. Deny from all
    11. </FilesMatch>
    12.      
    13. RewriteEngine On
    14. RewriteBase /
    15.  
    16. RewriteRule !\.(ico|jpeg|jpg|png|gif|swf|css|js)$ index.php [L]
    PHP:
    1.  
    2. <?php
    3. $url_args = array();
    4. if (strpos($url, '.html') === strlen($url) - 5) {
    5.     $url = str_replace('.html', '', $url);
    6. }
    7. $url_args = explode('/', $url);
    8. array_shift($url_args);
    9. if(count($url_args) < 9) {
    10.     $url_args = array_pad($url_args,9,'');
    11. }
    12.  
    Последнее выдрано из метода класса, т.е. каждый дальше как хочет, так и вертит тем, что в $url_args.
    Сейчас у меня 3 метода:
    getModule() - вызываемый модуль, т.е. example
    getMethod() - действие модуля, т.е. show. по сути может быть чем угодно, т.к. обработка осуществляется уже в самом модуле.
    getArgs(2) - в данном случае будет 1. 3, 4, ... и.т.д. сооствественно следующие позиции в урле. Т.е. getArgs(0) даст example, getArgs(1) даст show, т.е. getModule и getMethod просто обёртки для этих вызовов для удобства и наглядности.

    Раньше у меня было так:
    PHP:
    1. <?php
    2. $request = array();
    3. $req_uri = isset($_SERVER['REQUEST_URI']) ? ltrim($_SERVER['REQUEST_URI'], '/') : '';
    4. if ($req_uri) {
    5.     if (false !== ($pos = strpos($req_uri, '.html'))) {
    6.         $req_uri = substr($req_uri, 0, $pos);
    7.     }
    8.     $request = split('/', str_replace('.html', '', $req_uri) );
    9. }
    10. if (count($request) < 9) {
    11.     $request = array_pad($request, 9, '');
    12. }
    13. define('PAGE',   $request[0]);
    14. define('ACTION', $request[1]);
    15. define('ARG1',   $request[2]);
    16. define('ARG2',   $request[3]);
    17. define('ARG3',   $request[4]);
    18. define('ARG4',   $request[5]);
    19. define('ARG5',   $request[6]);
    20. define('ARG6',   $request[7]);
    21. define('ARG7',   $request[8]);
    22.  
    Тоже удобно, при этом реально всё глобально. Но мы с Luge решили что первый подход более правильный по нашему мнению.
     
  9. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    а еще у меня возникают сложности на следующем этапе:
    когда мы показываем страницу, к примеру список товаров, которые находятся в категории холодильники, ссылки на эти товары должны приводиться к ЧПУшному виду. Причем я хочу делать ЧПУ нескольких видов:

    1) /model_holodilnika
    2) /model_holodilnika.html
    ...

    С учетом того, что информация о том, как должен выглядеть URL находится в другой таблице, у меня возникают некоторые сложности.
    1) Нужно выбрать все записи из этой таблицы?
    2) Нужно на каждый выводимый товар цеплять + 1 запрос в эту таблицу?
    3) Нужно переделывать структуру таблицы.
     
  10. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    а, еще 4 вариант: отказаться от этой затеи и делать ЧПУ как все.
     
  11. d1gi

    d1gi Активный пользователь

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    о! :) а расскажите как "все" делают ЧПУ? ;)
     
  12. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
  13. d1gi

    d1gi Активный пользователь

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    ясно... ну это по типу друпала получается?

    а если надо сделать структуру например http://mysite/section/auto/catalog/toyota/carib/88-95/ то как обычно люди делают? :)

    если интересно могу расписать решение этой задачи на примере моего движка :)
     
  14. Koc

    Koc Активный пользователь

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    да, если есть время - опиши.
     
  15. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    d1gi
    модуль section получает урл auto/toyota/carib/88-95/ catalog в урле не нужен
    далее выбираем все публикации с ID 88-95
     
  16. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Psih
    а я таки решил юзать регулярки,

    Rewriter::AddType("category_id","[^\/]+\/category\/([^\/]+)\/?");
    $category_id=Rewriter::$get['category_id'];

    может не очень красиво, зато любой формат урла
    на тормознутость регулярок можно забить, т.к. текста для обработки немного(урлы обычно короткие), вызовов Rewriter'а немного (не больше 5 на весь цикл)
     
  17. d1gi

    d1gi Активный пользователь

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
  18. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    просто описал логически рациональный способ
     
  19. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Mr.M.I.T.
    Зато сложно. И в итоге в одном месте урл таким способом, в другом сяким и.т.д. :) Не проще использовать одну схему и всё? А уже в параметр можно запихать всё что можно. При поиске в GET я к примеру пихаю base64 строку и парсю её потом как мне надо. Так и с остальным.
     
  20. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Psih
    Вот я и хотел чтоб таким сяким, правдо не знаю зачем =) наверно чтобы было больше свободы при разработке
    да и текстовые ключи удобнее использовать
    а при поиске я вообще с GET работаю, т.е. как-то так /search/?q=query&field=comments
    d1gi
    опять всё сложно зачем пихать новости в рубрики
    сделай проще
    http://mysite/rubric/carib/88-95/
    http://mysite/news/new_carib2009.html
     
  21. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Mr.M.I.T.
    Зато PRIMARY KEY это самая быстрая выборка, какая только может быть. Особенно в больших таблицах. Зачем изобретать велосипед? Урлы никто не запоминает и не будет :) Меня прёт с урлов где транслитом пишут название статьи :D Нахера? :) Оно в SMS не поместится :D
     
  22. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Psih
    так я тоже так считаю http://www.php.ru/forum/viewtopic.php?p=158666#158666
    ты наверно перепутал с
    я имел ввиду что с таким урлом /category/10/page/3
    ты будешь работать
    getArg(0) getArg(1)
    а я
    Rewriter::$get['module'] Rewriter::$get['category_id']
    тоесть у меня ключи текстовые =)
     
  23. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    Psih
    для поисковика стороннего это будет не хорошо
     
  24. d1gi

    d1gi Активный пользователь

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    Koc
    выше упоминал 2 примера, которые вполне могут быть:
    http://mysite/rubric/auto/catalog/toyota/carib/88-95/
    http://mysite/rubric/auto/news/toyota/2 ... b2009.html

    добавлю к этим примерам еще:
    http://mysite/rubric/hi-fi/catalog/acou ... tion/f-30/
    http://mysite/rubric/bikes/catalog/mtb/ ... tions.html
    http://mysite/news/around_the_world/yahoo.html
    http://mysite/about/company/

    и допустим это один и тотже проект, притом он постоянно пополняется, развивается и меняется структурой внутри.

    попробую доходчиво описать как движок ЖЕ (JEngine) :) способен переваривать все эти ситуации :)
    рассмотрим на первомже примере http://mysite/rubric/auto/catalog/toyota/carib/88-95/ здесь у нас в структуре папок (ВИРТУАЛЬНЫХ папок! т.е. это табличка engine_folders) будет следующая вложенность:

    |{root folder} // собсна это и есть папка которая у нас подцеплена в корень сайта - http://mysite/
    |--| rubric // папка содержащае всякие рубрики, типа авто, вело, хобби и т.д...
    |---- | auto
    |------| catalog

    т.е. структура именно ПАПОК заканчивается на каталоге. в каталоге (в папке) подключен модуль самого каталога с определнными параметрами. затем, когда парсер разобрал первые папки запроса (т.е. /rubric/auto/catalog/) у него стоит флажочек, что дальнейший парсинг УРИ надо передать модулю (и разумеется указано какому именно модулю и с какими параметрами должен будет запуститься модуль, в нашем случае будет указано, что модуль каталога работает с категорией "auto") дальше парсер запускает модуль и отдаёт ему оставшийся кусок запроса (т.е. /toyota/carib/88-95/) , модуль каталога уже самостоятельyо разжевывает эту строчку по своей внутренней структуре и возвраoает парсеру, что он отработал успешно :)

    всё :) на этом работа парсера закончена и включаются функции по сбору объектов данных по распарсенному УРИ :) но это уже другой разговор :)
     
  25. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    слоожно