Как сделать ЧПУ для сайта на PHP

Как сделать ЧПУ для сайта на PHP

Написано Denis

Категория: Программирование

(Человеко-Понятные Урлы) или SEF (англ. Search Engines Friendly url). Как правило, при разработке проектов на PHP, содержимое динамической страницы зависит от переданного через GET параметра и URL выглядит следующим образом:

yourdomain.com/index.php?id=201


в данной случае намного аккуратнее смотрелась бы ссылка вида:

yourdomain.com/201/

yourdomain.com/201.html

а ещё лучше:

yourdomain.com/name-page.html

Как это сделать? Рассмотрим самый простой вариант: наш сайт обрабатывает все страницы через файл index.php и содержимое страницы определяется только одной переменной – id. В таком случае механизм преобразования из /index.php?id=201 в /name-page.html будет иметь следущий вид:

 

Блок-схема обработки ЧПУ (SEF)

 

1) Определяем существует ли запрашиваемый путь в реальности. Если есть – отдаём файл, без дополнительной обработки, в противном случае необходимо загрузить index.php, который обработает несуществующий ЧПУ. Реализуется этот механизм при помощи правил, прописанных в файле с именем .htaccess.

Файл .htaccess должен находиться в корневой директории. Создать и править .htaccess можно в обычном текстовом редакторе.

 

Содержимое файла .htaccess:

 

RewriteEngine On – разрешаем серверу преобразовывать URL.

RewriteBase / – устанавливаем базовый URL.

RewriteCond %{REQUEST_FILENAME} !-f – проверяем, что запрошенной директории не существует.

RewriteCond %{REQUEST_FILENAME} !-d – проверяем, что запрошенного файла не существует.

RewriteRule . /index.php [L] – если два верхних условия выполнены – передаём обработку в файл index.php

 

MySQL

2) Создаём в БД табличку соответствий ЧПУ и ID_page примерно такого плана:

 

SEF
varchar(255)
ID_page
int(11)
index 1
page 2
page-name 3

 

PHP

3) Содержимое файла index.php, из комментариев в коде ясно, как это работает.

 

 

Вот, в целом, и всё ;).

357 комментариев к статье Мне интересно ваше мнение!

  1. Grace:

    здравствуйте. спасибо за статью, но можно для тех, кто в танке, пояснить часть про запрос в БД, привести пример?

  2. Denis:

    Если речь идёт о MySQL, то хотя бы так:


    $query = "SELECT id_page FROM name_table WHERE sef = '".$sef_value."' LIMIT 1";

    mysql_connect (MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD);
    mysql_select_db (MYSQL_DB);
    $result = mysql_query ($query);

    if ($row = mysql_fetch_array($result)) {

    $ID_page = $row ['id_page'];
    }else{

    header("HTTP/1.0 404 Not Found");
    echo "Страница не существует";
    exit;
    }

  3. Михаил:

    Все это интересно, но хотелось бы поподробней, для чайников. Есть готовый сайт на движке стоит. Но пока дальше просто каталогов не продвинулся. А html поставить очень хочется в конце урл.

  4. Denis:

    Михаил, а в чём конкретно затруднение? Приведённый пример, по сути, является сильно упрощённой версией организации ЧПУ, если человек знаком с основами PHP, то проблем с пониманием в целом быть не должно.

  5. Михаил:

    А затруднение конкретно в том, что запрос выводит контент по ID, а нужно по keywords.

    Если бы разобрать на моем примере. Я где-то рядом уже, но еще не совсем.

    вот мой скрипт. То есть это запрос к базе данных на предмет нахождения определенного ID.

    function view() {
    global $conf, $template, $db, $header_page_title, $header_page_keyword, $news_config;

    $tdate = time();
    $id = ( isset($_GET[‘id’]) ) ? intval($_GET[‘id’]) : 0;
    $sql = “SELECT * FROM “.$conf[‘prefix’].”_mod_news WHERE id = ‘$id’ AND newsdate sql_query($sql);
    $row = $db->sql_fetchrow($result);
    $header_page_title = $row[‘title’];
    $header_page_keyword = “$row[keywords] $row[home_text]”;

  6. Михаил:

    Куда же вы пропали, Денис?

    Рою, но никак вырыть не могу. И автор пропал!!!!

  7. Denis:

    Выходные, отдыхаю…

    function view() – вынимает информацию для всех страниц сайта или только для какой-то его части, раздела? Смущает название таблицы mod_news.

    Это тоже настораживает:
    global $conf, $template, $db, $header_page_title, $header_page_keyword, $news_config;

    Не по теме ЧПУ, а просто как разумность подхода.

  8. Михаил:

    Это кусок кода из модуля просмотра новостей. И вынимает только определенною новость по ID.
    mod_news – это название таблицы в БД.
    Ну а перечисление глобальных переменных – это я не знаю – так авторы написали)) Просто у меня старый сайт на этом движке. Зовется движок SmallNuke.
    Не хочется его 9сайт) переносить на другой двиг, да и страниц много проиндексированных. Но вот одолела меня идея фикс сделать ЧПУ. Не по ID? по нему у меня сделано уже давно. А хочется по KEYWORDS, чтобы выводилось.

    в таблице mod_news есть поле keywords, но никак не хочет за него цеплять.

    В принципе движок мне нравится. Простой и я с ним давно работаю, много сайтов на нем сделал, много чего там сам перекрутил под себя, но вот ЧПУ никак не могу осилить.

    name.info/prodolgenie-istorii-grafa.html
    я добился вот такого, но это совсем не то, что надо. Я просто пишу реврайты в htaccess/ Но это же полная чушь такой фигней заниматься.

    Имеется ввиду вид урла написанный транслитом

    Я теоретически-то понимаю о чем речь, но где-то не совсем правильно делаю, а где понять не могу. ЗнаниеФ не хватает, видимо.

  9. Denis:

    Полагаю поле keywords там совсем для другой цели

    name.info/Content/News/101
    а хочется:
    name.info/Content/News/press-reliz.html
    или хотя бы
    name.info/Content/News/press-reliz
    ?

  10. Михаил:

    Ага. Вот именно так и хочется. Уже перерыта вся сеть. Твой метод самый реальный. Причем вроде как работает он. И если ввести урл такого вида, как он есть в движке, то есть с амперсандами и знаками равно – появляется сообщение о неправильном урле – недопустимые символы, но далее должна быть выкладка из базы, а скрипт не понимает писанного.

    Как раз поле keywords доступно для редактирования из админки. Вот его-то я и хочу использовать в качестве псевдонима для урла

  11. Denis:

    Мой “метод” самый обычный, объясняющий основы ЧПУ, это как:

    echo “Hello World !!!”;

    для начинающих изучать PHP.

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

    К примеру, в вашей ситуации до конца не понятно, как реализованный алгоритм SEF разбирает ссылки

    name.info/Content/News/cat13
    и
    name.info/Content/News/778

    В первом случае это категория новостей, во втором сама новость.
    Не забывайте о другой проблеме – у вас, наверняка, меню новостей формируется автоматически, значит надо подвергать доработке скрипт, печатающий меню и т. д.

  12. Михаил:

    Да всё тут понятно, как он ссылки разбирает, просто стоит правило в htaccess? которое тупо режет всю техническую символику. ну спасибо, что поучаствовал)) буду разбираться.

  13. Denis:

    Вообще я имел ввиду, что из куска кода не видно, как News отличает cat13 от 778, т.е. когда переменная вынимается GET, чем определяется/отделяется cat? Можно сделать разбор для новости – искать imya-novosti.html, после запрашивать соответствие в вашем keywords, но в какой-то момент сделаете вы новость name.info/Content/News/catalog-ogurcov.html и получите ошибку т.к. нет категории новостей alog-ogurcov.html.

  14. Михаил:

    В принципе, мне и нужно так – искать imiy-novosti.html/
    Родные урлы имеют вот такой вид – /index.php?go=News&in=view&id=$1
    то есть я реврайтом режу /index.php?go= и &in=view&id=
    в результате остается News/$1
    То есть я сам рулю, где категорию поставить, а где имя_файла.html
    И если я найду решение вытягивать текст новости по keywords – то менять каталоги или категории – это вообще не проблема.
    То есть кусок кода идентичен для всех манипуляций и в нем явно прослеживается вывод текста по ID.
    Скорее всего нужно искать функцию, которая и определяет скрипту как искать…
    И если её найти – то вообще ничего не нужно. Ни реврайтов, ни правил, ни сравнений. Просто скрипт по keywords будет дергать и все. А для этого нужно правильно запрос к базе составить… Вот проблема в чем. А способ, который ты описал – он опять же режет техническую инфу и не более того.
    А вот если реализовать такое /index.php?go=News&in=view&id=imja-novosti.html
    то порезать все лишнее труда не составит

  15. Denis:

    Задача ЧПУ в том и состоит, что бы убрать из URL “лишнюю” информацию.

    Полагаю в этой строке пропущен кусок кода, посмотрите ещё раз:

    $sql = «SELECT * FROM «.$conf['prefix'].»_mod_news WHERE id = ‘$id’ AND newsdate sql_query($sql);

  16. Михаил:

    Да, нет, не пропущен, все работает, возможно, Денис, нужно что-то добавить? Или МОЖНО добавить?
    Лишнюю-то информацию я убираю, но меня интересует не id, а keywords/
    А может как-то значение PRIMARY KEY в БД влиять на способ выдачи контента из базы?

  17. Михаил:

    В общем после долгих раздумий пришел я к такому мнению, что id страницы необходим. Ведь когда много контента, а у меня его действительно много, если исключить id – то возникнут трудности с администрированием. Удалением, преределкой и так далее. Так что остановился я на варианте 6-kak-ja-pitalsa-rabotat-s-siwegoi.html
    На мой взгяд – это самое оптимально – и ссылка читаемая и номер страницы присутствует.

    И всего одно правило в htaccess прописано.

  18. Denis:

    Михаил, так:


    $sql = «SELECT * FROM «.$conf['prefix'].»_mod_news WHERE id = ‘$id’ AND newsdate sql_query($sql);


    работать не может, вы присваиваете переменной $sql строку :

    $sql = «SELECT * FROM «.$conf['prefix'].»_mod_news WHERE id = ‘$id’ AND newsdate [тут какой-то оператор и значение] ";

    а потом вызываете функцию:

    $result = sql_query($sql);

    А у вас всё в кучу записано.

    По существу вопроса:

    замените:

    $id = ( isset($_GET['id']) ) ? intval($_GET['id']) : 0;

    на

    $id = $_GET['id'];

    в следующей строке замените:

    id = ‘$id’

    на:

    keywords = ‘$id’

    Если всё заработает, то надо будет переделать

    $id = $_GET['id'];

    на код с проверкой, но я сомневаюсь, что существующими правилами будет верно сформирован реальный URL.

    PRIMARY KEY (первичный ключ), на решение вашей задачи он никак не влияет. Думаю, что в вашей таблице он стоит на столбце id. Если вы начнёте делать выборку по столбцу keywords, логично будет, как минимум, сделать его индекс, при этом изначально у вас keywords не является уникальным для таблица, а при вашей переделке должно стать таким.

    Так что остановился я на варианте 6-kak-ja-pitalsa-rabotat-s-siwegoi.html

    Если всё работает – почему бы и нет, нормальная ссылка.

  19. Denis:

    Михаил, вот правильный кусок кода:


    $sql = "SELECT * FROM ".$conf['prefix']."_mod_news WHERE id = ‘$id’ AND newsdate < '$tdate'"; $result = $db->sql_query($sql);

  20. Сергей:

    jquery?


Оставьте комментарий Высказывайте свои мысли по этой теме


+ 8 = тринадцать