2010
01.14

Нашёл на одном из блогов реализацию ЧПУ и решил внести свою лепту. ЧПУ – человеко понятный урл. На аглийском наиболее популярное название User Friendly URL. С какого-то перепугу разработчики решили, что стандартный урл с гет переменными непонятен и покатилось. Сначала сравним варианты для вывода списка новостей категории test отсортированного по date:
news.php?category=test&sort=date – стандартный подход, вроде всё понятно ключ=значение
news/category/test/sort/date/ – если убрать выделение, то не понятно где ключ, а где значение
news/test/date/ кратко, но довольно путано, обязательный порадок, трудно изменять
news/category:test/sort:date/ – этот вариант хорош, так же нагляден как класика и даже чуть короче
news.test.date – краткий, но не информативный, есть один плюс – такие страницы без тайтла сохраняются с нормальным названием.

Теперь рассмотрим классический разбор: через mod_rewrite apache пересылаем запрос на index.php, а там уже разбираем с помощью php. Разбор в самом mode_rewrite не очень хорошая идея, так как постоянно нужно модифицировать .htaccess. Самое популярное правило:

.htaccess ложится в корень сайта и прописывается (код из wordpress)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Сразу проверка есть ли модуль, а дальше если нет файла или директории с указаным адрессом, то пересылаем на index.php, а там разбираем $_SERVER["REQUEST_URI"]. У правила есть один огромный недостаток – разработчики постоянно забывают, что браузер запрашивает кроме страницы favicon.ico – для маленькой иконки в названии сайта. И если такого файла нету, то на index.php посылается и этот запрос, тем самым нагрузка удваивается. Вторая проблема – создал папку с названием модуля и всё, накрылся реврайт.

Я учёл эти проблемы и запихнул всё что должно быть доступно из вне в папку public, а затем для неё и favicon.ico отключил реврайт.

RewriteEngine on
RewriteRule !^(public/|favicon\.ico) index.php [L]

Ну а дальше по отработанной схеме. Из недостатков – ограничение на название public. Из плюсов – теперь только в публик можно не придерживаться ЧПУ фреймворка, например, tinymce в папке public может использовать урлы с гет переменными, а если перенести за пределы, то всё будет работать через единую точку входа.

Похожие posts:

  1. Flash сообщения 2
  2. Работа с формами
  3. SPL в PHP: ArrayObject

4 комментариев

Прокомментировать
  1. Это чтоб дописывал слеш в конце (для унификации урлов)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)([^/]{1})$ http://%{HTTP_HOST}/$1$2/ [R=301,L]

    А это разбирает урл на папочки
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^([^/]+)/([^/]*)$ index.php?mode=url&node[]=$1 [QSA]

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/([^/]+)/$ $1/?node[]=$2 [NE,QSA]

    И все, htaccess модифицировать не придется, а гибкость больше (легче делать редиректы неправильных урлов на правильные). Да и по быстродействию этот способ побыстрее на коротких урлах (если считать верификацию маски пути)

    Условия на папку/файл можно убрать, просто я считаю что реальный файл должен быть приоритетней виртуального

  2. по мне так лучше mod rewrite
    переписывать придется стольео же раз, сколько пришлось бы править php, да и нагрузки меньше + можно отфильтровать get данные прямо сервером не доходя до скрипта, а это дополнительная безопасность. т.е напимер в isers/id/
    вместо id не смогут подставить что-то кроме цифр.

    • так php код вовсе не придётся править.
      $r = new Request(‘news/list/sort:date/’);
      $r->getController() – news
      $r->getAction() – list
      $r->getParam(‘sort’) – date
      $r = new Request(‘news/list/page:2/sort:date/’);
      $->getParam(‘sort’) – sort
      $r->getParamInd(‘page’) – 2
      а регулярку бы каждый раз пришлось переписывать, а так же следить за форматом.

  3. Я тоже делал через одну точку входа, мне так удобно, правда я еще mysql приплел – http://js-php.ru/web-development/apache-mod_rewrite-php-mysql/

    Неплохо кстати это дело в симфони организовано, там тоже вроде все через одну точку входа, но настройки лежат в ymml формате, все никак руки до него не дойдут, что за формат такой :)