ЧПУ своими руками (PHP)

13 июня 2009
Просмотров: 51595Обсудить
Рубрика: Программирование -> PHP

ЧПУ (ЧеловекоПонятныеУрлы) - это ссылка вида site.com/page/2 вместо site.com/index.php?option=page&page_id=2 . Приемущества использования ЧПУ думаю всем понятны. Это более короткие, простые и понятные урлы. К тому же "ходят слухи", что поисковикам они "больше нравятся".   Последний факт я не проверял и было б странно, если б поисковики отсеивали или как то ограничивали ссылки, которые им "не нравятся", но если таке мнение есть - к ним надо прислушаться... Причина, из-за которой я начал смотреть в сторону ЧПУ - многие заказчики очень хотят их видеть у себя на сайте ...

Разработано достаточно много способов создания ЧПУ :

  1. mod_rewrite - часто используемая технология. Идея заключается в установке спецового модуля к апачу и добавлению правил для преобразования короткого урла в полный в файл .htaccess
  2. RewriteRule ^([^/]*)\.rss  /rss.php?type=$1 [L]

    + : достаточно простой в реализации метод - накатал в .htaccess  правила и все тут

    -: надо, чтоб на сервере был установлен собственно mod_rewrite, при обьемном сайте - накопление правил в .htaccess

  3. FileMatch - Основан на директиве FilesMatch, которая в Апаче является core feature. Все просто. Пишем опять же в .htaccess

    Action throw /index.php <FilesMatch "^([^.]+)$">
    ForceType throw
    </FilesMatch>
    <FilesMatch index.php>
    ForceType application/x-httpd-php
    </FilesMatch>
  4. Эти директивы будут перенаправлять все запросы , не содержащие точки , на index.php. Дальше разобрать запрос - не особо сложно...

    +:  та же простота в реализации

    -: надо, чтоб на сервере был установлен модуль mod_action

  5. ErrorDocument - основан на дерективах в .htaccess файле для переброски запросов с несуществующих урлы на указаный файл. Для этого в .htaccess надо добавить:
ErrorDocument 404 /index.php ErrorDocument 401 /index.php

+: ИМХО самый простой способ, ничего устанавливать на сервере не надо,  в индексе получил запрос , обработал и радуешься

-: на сервере в логах накапливается сообщения об 404 урлах... надо отключать логирование таких ошибок.

Еще стоит сказать, что даже после перенаправления запроса   с несуществующего урла на существующий файл, сервер покажет нужную страницу, но все ровно вернет стаату 404 для этой страницы. Чтоб этого не было - надо вначало index.php добавить

header("http/1.0 200 Ok");

Уверен, что есть еще множество методов, но мы ограничимся этими.

В моем случае первый способ брать смысла не было ... непонятно будет ли на сервере у хостера стоять mod_rewrite (хотя обычно стоит ;)). Второй - у меня не заработал ... даже не знаю почему  ;( Остался  третий способ. Он как раз заработал как надо. Вся сложность заключалась в преобразовании ЧПУ-шного урла и обычный и наоборот. CMS Joomla (и многие другие видимо) используют для этих целей базу данных и динамически генерят новые урлы. Мну это не прет ... бо поработав с той же джумлой убедился, что львиная доля времени формирования страницы уходит на формирование и поиск этих урлов в БД ... Хотелось найти решение без баз данных, и я его нашел.  Суть заключается в наборе правил вида:

$linksUrls[]=array('pages',"do=?");
$linksUrls[]=array('pages/?',"do=?&pid=?");

Для обработки таких урлов я написал спецовый класс (сам класс и файлы примеров можно найти вконце статьи). Разбирать сам класс мы не будем, а посомтрим способы его приминения на примерах.

  1. Подключение и использование ЧПУ на сайте
  2. $links=new Links($url,$use_ufu); //$url - название сайта. Будет добавляться к ссылам при генерации, $use_ufu (0\1) - использовать ЧПУ или нет
    if ($use_ufu == 1) {
    require_once("Links.rules.php"); // подгружаем файл с правилами
    if (isset($linksUrls) && is_array($linksUrls)) // если есть массив с правилами - делаем инициализацию
    $links->init($linksUrls);
    }

    Содержимое файла Links.rules.php :

    $linksUrls=array();
    $linksUrls[]=array('news',"do=?");
    $linksUrls[]=array('news/?',"do=?&news_id=?");
    // mod pages
    $linksUrls[]=array('pages',"do=?");
    $linksUrls[]=array('pages/?',"do=?&pid=?");

  3. Разбор ЧПУ-шного урла и формирование GET  запроса
  4. if (isset($_SERVER['REDIRECT_STATUS']) && $_SERVER['REDIRECT_STATUS'] == '404') {
    $url=$_SERVER['REQUEST_URI'];
    if (!$links->parseURL($url)) {
    // error 404;
    die('Sorry, page not found'');
    }
    }
    print_r($_GET);

    Если все прошло хорошо - в массив $_GET  будут добавлены переменные, которые б использовались при обычном запросе. Следует сказать, что запрос должен быть вида /pages/2  ю Следует так же указать, что можно указывать переменные, не определенные в правилах как в обычном запросе /pages/2?foo=5

  5. Генерация ЧПУ из обычного запроса
$links->createUFU('index.php?do=pages');
// результат: site.com/pages/

Я конечно понимаю, что способ не есть универсальным, зато он достаточно простой в реализации, простов в применении.

В любом случае буду благодарен за любые коментарии\критику, поскольку они могут помочь усовершенствовать код\метод\способ ;)

TODO: Сейчас ЧПУ-шный урл формируется соединением значений из обычного урла с помощью "/". В дальнейшем планирую убрать привязку к порядку следования переменных в обычном урле.

Класс и примеры лежат тут.

UPD: более адекватный метод описан в статье ЧПУ своими

руками (PHP). Хранение ЧПУ в базе данных

google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru
Метки: ,


Комментариев: 10
Подписаться на комментарии по RSS
  • #12009-09-06 в 16:48:53roknsev (анонимно)

    Вобще, спасибо за статью, раньше пробовал через .htaccess но не получалось, сейчас буду пробовать через твой класс)))


  • #22009-09-06 в 18:09:29YAAP (анонимно)

    Пробуйте, отпишитесь как все прошло.

    ЗЫ: я сейчас пишу еще одну статью по ЧПУ (которая раскрывает принцип независимых от системы ЧПУ .. ).

    ЗЫЫ: В описанной технологии (а именно ErrorDocument 404 /index.php) есть существенный недостаток - невозможность обработать пост данные... Поэтому советую все таки использовать мод реврайт для перенаправления всех запросов на индексную страницу...


  • #32010-01-11 в 21:44:02Алексей (анонимно)

    Способ принимается, хотя...

    есть еще один вариант - использовать ссылки вида http://my.com/?/news/2 при этом запрос попадает ессесно на index.php

    что получаем в $_SERVER["REQUEST_URI"]? Строку вида: /?/news/2.

    Единственный недостаток - знак вопроса. Плюсы: ничего на сервер не ставим, .htaccess и логи не трогаем. grin


  • #42010-01-12 в 01:29:15yaap

    @Алексей (анонимно)

    имхо проще и лучше поставить в .htaccess реврайн на индекс (именно реврайн, не директори индекс). Так логи тоже не будут засоряться ... А вот знак вопроса в урле - лично мне не нравится =)

    зы% есть еще вариант хранить урлы в базе данных, как это делает та же джумла (точнее SEF), но этот вариант подходить ток для небольших сайтов ...

    этот, и еще пару вариантов я как нить опишу в статье... хай ток время появится =)


  • #52011-01-18 в 11:51:40Fan4ik (анонимно)

    А ще краще використовувати паттерн маршрутизатора, який фільтрує передаваємі параметри через preg_match, такий як використали в ZendFramework cheese


  • #62011-06-09 в 17:40:02о_О (анонимно)

    №5: Це точно! Інфа 100% wink


  • #72011-10-14 в 13:53:44Аноним (анонимно)

    №5: Це точно! Інфа 100%


  • Спасибо за труд, но у меня скрипт не работает.

    Тестировал на локалке (денвер). Извлек файлы в localhost/4pu. Заменил в index.php адрес на "localhost/4pu" (пробовал так-же по-разному его прописывать). Когда в адр. строку вставляю http://localhost/4pu/pages/2/ то денвер выдает ошибку, мол страница не найдена. В чем может быть причина?


  • #92012-03-05 в 16:15:45yaap

    @Комментатор 9

    В некорректных настройках.

    Если http://localhost/4pu/pages/2/ говорит, что такой страницы нет - значит вы не перенаправляэте все запросы на индексный файл, который будет отрабатывать эти сами запросы..


  • #102012-12-24 в 19:18:02Аноним (анонимно)

    Класс хороший, но пришлось кучу раз доделать и переделать. Баг на баге gulp. То не работает с двумя ?, то название через - не выходит.


Оставьте комментарий!

Не регистрировать/аноним

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email.
(При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д.)



grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

(обязательно)