Делаем чпу

В своей первой статье про mod_rewrite я рассказал, как сделать замену url на одно ключевое слово. Теперь можно рассмотреть более сложны варианты.
Начнём с url, которые имеют несколько параметров. На практике это обычно какой-либо предмет и его категория.


Предположим наш сайт содержит огромное кол-во музыки. Которая распределена по жанрам, а жанры уже разбиты на группы.
Тогда замененная ссылка будет выглядеть примерно так:

https://mus_site.net/music/S1 /G1.html

А ссылка обработчика допустим вот так:

https://mus_site.net/show_music.php?style=1&group=1

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

RewriteRule ^music/S([0-9]*)/G([0-9]*)\.html$ /show_music.php?style=$1&group=$2

url получается хоть и привлекательный, но не совсем понятный. Надо бы добавить ключевых слов. Чтобы вышло примерно следующее:

https://mus_site.net/music/style/group.html

Но сделать это уже сложнее, так как явных идентификаторов в такой ссылке нету. Можно добавить в таблицу поле, которое будет связывать url с ключевиками и url, созданные обработчиком. А можно добавить идентификаторы к ключевым словам и получить вот такой url:

https://mus_site.net/music/style-s1/group-g1.html

Такая ссылка содержит ключевые слова и подогнать её под обработчик не составит труда.

RewriteRule ^.*-s([0-9]+)/.*-g([0-9]+)\.html$
/rewrite/index.php?style=$1&group=$2 [L]

Учтите, что в файле .htaccess писать правило надо в одну строчку.

Теперь смоделируем реальную ситуацию, в которой создание ссылок положим на плечи php. Представим, что у сайта есть бд в которой хранятся стили и музыкальные группы. Наша задача из всего этого сделать ссылку, которую поймет наше последнее правило mod_rewrite.
В одной умной книжке подобная задача уже была решена с помощью двух функций, которые мы сейчас и рассмотрим.

functions.php

define('SITE', 'https://localhost/rewrite/');
//приводим url к нормальному виду
function clear_url($str)
{
$good_liters= '#[^-a-zA-Z0-9_]#';
//оставляем латиницу, подчеркивания, пробелы и дефисы.
$str = preg_replace($good_liters, '', $str);

//откусываем пробелы по сторонам
$str = trim($str);
//и всё подменяем  дефисами
$str = preg_replace('#[-_ ]+#', '-', $str);

return $str;
}

//делаем ссылку с ключевиками
function create_url($cat_name,$cat_id,$group_name,$group_id)
{
$clear_cat_name = clear_url($cat_name);
$clear_group_name = clear_url($group_name);

$url = SITE.$clear_cat_name.'-s'.$cat_id .'/'.
$clear_group_name.'-g'.$group_id.'.html';

return $url;

}
?>

nav.html

index.php

include("functions.php");
include("nav.html");
echo 'стиль группы c номером  '.$_REQUEST['style'].' а сама группа под номером '.$_REQUEST['group'];
?>

Как вы можете догадаться в строчку
create_url(“dance_music”,2,”pop group”,32)
нужно просто подставить значения при выводе из бд. И всё будет как надо 😉





Читайте также:



24 Ответов на “Делаем чпу”

  1. Оппа. Сразу в закладки. Наконец-то толковая статья как преобразовать url’ы. А то есть одна CMS без чпу, а с mod_rewrite у меня дружба складываться не хочет)).

  2. Толково все расписал. А то в остальных статьях только теория, а как решить конкретную задачу получить из
    [ссылка] человеческий url полдня приходится “догонять”. Респект!

  3. Прикольно, еадо будет обязательно попробовать

  4. Отлично написано, доходчиво, спасибо. А может есть че почитать в электронном виде по mod_rewrite и по созданию правил в htaccess? Можно на мыло, или ссылку на мыло, где можно скачать. Был бы благодарен.

  5. novice

    Фридл Дж. Регулярные выражения (2-е изд.)
    Тока предупреждаю, книга сложна для восприятия :)
    вот линк [ссылка]
    2-е функции взял из книги поисковая оптимизация для профессионалов, только у меня она в бумажном виде :)

  6. Да книга действительно не из простых… Ну ничего, трудности нас не пугают. Спасибо за линк :)

  7. ant

    Хорошо написано. Спасибо, понял)

  8. bibendi

    Вообще лучше не городить много правил в htaccess, т.к. это сильно влияет на скорость. А подходить к этому вопросу с точки зрения mvc. т.е. ссылка всегда имеет вид [ссылка]

    Тогда для этого нам понадобится всего то:
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* index.php

    поясняю: если файл не найден на сервере, то запрос будет отдан в index.php, где уже роутер будет парсить $_SERVER[‘REDIRECT_URL’] и загружать определённый контролёр и вызывать его нужный метод

  9. cryptus

    Читал где-то, что много правил в .htaccess тормозят работу, но нигде подробных тестов так и не нашел. Рутер внутри php - это конечно более гибкая идея, согласен.

  10. “Рутер внутри php - это конечно более гибкая идея, согласен”
    многие движки используют такой подход. Например WordPress (этот блог), LiveStreet (движок аля Хабр)

  11. Добавлю еще про “Рутер внутри php”. Этот подход используют пожалуй все известные php-фрэймворки (Zend, Symfony и др)

  12. horser

    Спасибо за код, у меня почти все получилось. Но есть вопрос –
    Как сделать, что бы параметр id по которому опреляется вывод результата, не выводился в адресной строке, к примеру у меня благодаря вашему примеру получается

    [ссылка]
    а нужно
    [ссылка]

    у меня без идентификатора не выводит нужный результат.

    P.S. я новичек, поэтому просьба ответить на пальцах, заранее спасибо

  13. novice

    В этом случае, если Вы не хотите передавать идентификатор через GET-запрос (чтобы его не было видно в адресной строке другими словами), есть два варианта: перед нажатием на ссылку записать идентификатор в сессию и считывать его оттуда. Второй вариант: передавать его через POST. В любом случае нужно как-то передать этот идентификатор скрипту, иначе получится волшебство :)

  14. horser

    Что здесь нужно поправить?

    1 страница
    <?php
    $result = mysql_query (“SELECT * FROM portfolio”, $database);
    $myrow = mysql_fetch_array($result);
    do {
    printf (”
    %s

    “, create_url($myrow[“product”], $myrow[“page”]), $myrow[“icon”], $myrow[“date”]);
    }

    while ($myrow = mysql_fetch_array($result));
    ?>

    2 страница

  15. novice

    Непонятно, зачем здесь цикл do..while, если можно было обойтись просто while. И вместо printf можно использовать просто echo. Тут много чего я бы поправил

  16. horser

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

    2. страница

  17. horser
  18. horser

    $database = mysql_connect(…);

    $result = mysql_query(“SELECT * FROM portfolio WHERE id=’$id'”, $database);
    $myrow = mysql_fetch_array($result);

  19. S.N.K

    horser, цикл do…whilу необходим, иначе при выводе потеряешь одну строку.
    Novice, скажи точно что ты хочешь получить? толи ты передаешь id другим путем, то ли ты вообще не хочешь передавать id. Что конкретно ты хочешь получить?

  20. novice

    S.N.K, видимо ты перепутал меня с horser’ом 😉

  21. Alexx

    Сразу начал делать сайт со ссылками вида “https://site.ru/index.php&p=1&id=4c7319c21570aeeca6c8774f216c6656&page=1″ типа для невозможности подбора цифр в “р”. Можно ли такие ссылки привести к виду “https://site.ru/news/page1/” ?

  22. novice

    Можно, если переменную id будете передавать методом POST.

  23. очень интересно написано, ну у меня ни чего не получилось (((

  24. Как все запутано, я ничего не понял.


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map