Главная » FAQ по ЧПУ (человекопонятные URL)
Как разбить URL на переменные?
Вводная:
Помогите разбить URL на переменные: http://name.ru/content/article/1/Ответ:
Получить URL так $url = $_SERVER['REQUEST_URI'];
Далее, воспользоваться командой explodeВариант от Нечто (mod_rewrite и разбор пути средствами PHP):Правила mod_rewrite:
Благодаря вышеприведенным правилам,вместо виртуального /some/interesting/page/ будет вызван URI/index.php/some/interesting/page, а обращения к реально существующимфайлам обрабатываться не будут.Разбор пути:// Достаем переменную окружения, содержащую путь; если она не задана, находимся в корне.
$URI = (isset( $_SERVER [ 'PATH_INFO' ])) ? $_SERVER [ 'PATH_INFO' ] : '' ;// Разбиваем путь на элементы, фильтруя пустые значения и
// восстановливая численную последовательность индексов.
// Пустые значения образуются при разбивке путей типа //another///interesting/page///.
$URIelements = array_values ( array_filter ( explode ( '/' , $URI )));print_r ( $URIelemets );
?> Впоследствии элементы запроса можно перебрать на предмет каких-тоключевых системных значений, а также склеить обратно с помощью implode.Как удобнее хранить данные о разделах сайта

Вариант 1
Базовые поля таблицы:
id - int - идентификатор страницы
title - varchar - заголовок страницы
url - varchar - полный URL страницы Вообщем-то, весь вариант заключается в том, что сохраняются все полные URL для всех существуют страниц, то есть нет страниц с параметром, который может принимать любое значение(числовое, например),либо все допустимые значения строго описаны.ИТОГО:
* Метод прост тем, что не нужны большие усилия для его реализации, достаточно взять пришедший URL и попыпаться выбрать его из базы
* Он не может быть использован при большом числе динамического контента(например, лента новостей), так как в таком случае получается довольно большая база и необходимо контролировать все изменения, влекущие к созданию нового URL Вариант 2
Базовые поля таблицы(pages):
id - int - идентификатор страницы
url - varchar - URL страницы
handler - varchar - файл-обработчикДовольно распространена ситуация, когда вывод подкатегорий почтине отличается друг от друга. Единственным отличием является группа, ккоторой принадлежит контент.
Например, /news/sport и /news/tv израздела /news различаются только тем, что, например, в sql-запросе вусловии WHERE стоят разные группы(sport и tv, соответственно).
Тогда как в /news группы вообще не учитываются.
Из-заэтого совершенно излишне делать отдельные обработчики для каждого URL,точнее, создание обработчиков сведётся к копированию и изменению 1запроса(не забывайте про то, что при таком копировании при обнаружениикакой-то ошибки вам придётся копировать всё заново).При таком подходе необходимо добавить в БД 1 запись:
url handler
/news/ news.phpПри загрузке страницы для выбора нужного файла-обработчика действуем по следующей схеме:
пытаемся выбрать из БД полный
если нет такого URL, то отрезаем от него часть и возвращаемся в п.1 для полученного URL
отдаём управление handler'уИТОГО:
Удобно для хранения страниц с параметрами (дата, номер поиска и т.д.), так как парамеры будут извлечены в отдельный массив
Подопредeлённые условиях можно создать отдельный обработчик(например,существует категория новостей, где используется отличный от остальныхновостей формат, либо данные хранятся в другой таблице)
В случае,если не существует страница, например, /shop, то отобразаится главнаястраница, что может быть нежелательные, хотя и можно модифицироватькод, чтобы при определённых условиях(например, нет страницы в "первомуровне") выдавалась страница с 404 ошибкойПримеры поиска:// Удаляем лишние слеши, в начале и конце $url точно будет /
$url = preg_replace ( '#/+#' , '/' , '/' . $_SERVER [ 'REQUEST_URI' ]. '/' );
$flag = FALSE ; // Найдем обработчик?
$param = array(); // Массив для параметровwhile ( $url != '/' && ! $flag ) {
// Пытаемся выбрать обработчик для страницы
$result = mysql_query ( "SELECT `handler` FROM `pages` WHERE `url`='" . $url . "' LIMIT 1" , $db );
if (! mysql_num_rows ( $result )) {
$url = substr ( $url , 0 , strlen ( $url ) - 1 ); // Отрезаем / на конце $url
$pos = strrpos ( $url , '/' ) + 1 ;
$param [] = substr ( $url , $pos ); // Отрезаем параметр
$url = substr ( $url , 0 , $pos ); // Получаем новый $url
} else {
$row = mysql_fetch_assoc ( $result ); // Получаем строку
$handler = $row [ 'handler' ]; // Помещяем обработчик в $handler
$flag = TRUE ;
}
unset( $result );
}
// "Переворачиваем" массив с параметрами, чтобы они шли по порядку следования в URL
$param = array_reverse ( $param );
?> Данный код является ТОЛЬКО примером
В итоге мы получаем все параметры в массиве $param, файл-обработчик в $handler.Вариант 3
Базовые поля таблицы(pages):
id - int - идентификатор страницы
parent_id - int - родитель
handler - varchar - обработчик, занимающийся страницей
url - varchar - часть URL между //Метод заключается в том, что используется древовидная структура и построение дерева происходит в PHP-скрипте.Допустим, есть URL: /news/sport/smth
Выбираем из базы:Дальше остается только немного обработать результаты выборки.ИТОГО:
* При большой вложенности метод должен быть довольно медленным
* Во многом он зависит от реализации
* В зависимости от реализации, метод позволяет разбирать структуры подобные такой: //Вариант 4Базовые поля таблицы аналогичны Варианту 3.Вариант работоспособен, если для хранения разделов будет использоваться Adjacency List.
Вариант генерации запроса, не требующего дальнейшего разбора:$url = trim ( strtolower ( $url ), '/' );
$_url = explode ( '/' , $url );
$_url = array_filter ( $_url , 'strlen' );$sql1 = 't0.id' ;
$sql2 = $sql3 = '' ;
for( $i = 1 , $c = sizeof ( $_url ); $i < $c ; $i ++)
{
$sql1 = "IF (t" . $i . ".id IS NOT NULL, t" . $i . ".id, " . $sql1 . ")" ;
$sql2 .= "+IF(t" . $i . ".id IS NULL,0,1)" ;
$sql3 .= "LEFT JOIN structure t" . $i . " ON (t" . $i . ".parent_id = t" . ( $i - 1 ) . ".id AND t" .
$i . ".url = " . $this -> db -> Quote ( $_url [ $i ]) . ") " ;
}
$pageId = $this -> db -> _Query ( "SELECT " . $sql1 . " AS id, 1" . $sql2 . " AS count FROM structure t0 " .
$sql3 . " WHERE t0.parent_id = 0 AND t0.url = " . $this -> db -> Quote ( $_url [ 0 ]));
$this -> debug -> Trace_R ( $pageId );
?> Получаем:Array
(
[ id ] => 3
[ param ] => 1
) Я думаю надо помимо id еще сразу тянуть все нужные данные (название раздела, обработчик и т.д.).ИТОГО:
* Максимальное число вложенностей ограничено засчёт того, что существует максимальное число JOIN в БД
*Метод может быть медлительным, так как используется JOIN, при большихобъёмах базы и большой вложенности скрипт может вылезти за временноеограничениеВариант 5
Базовые поля страницы(pages):
id - int - идентификатор страницы
handler - varchar - обработчик
url - varchar - регулярное выражение для URL, соответствующее обработчикуЛирическое отступление: вообще, мне этот метод был навеянpython'овским django, в котором именно при помощи регулярных выраженийперечислялась обработка всех допустимых URL. Данный вариант являетсяреализацией части функционала, предоставляемым Django с использованиемБД.Суть метода заключается в том, что в базе хранятся регулярныевыражения, которые соответствуют URL. Выборка нужных страницосуществляется посредством использования MySQL'оного REGEXP.Если немного расширить данный способ, то в PHP при помощиодного preg_match можно получить все параметры. А дальше уж насколькофантазии хватит.ИТОГО:
* Говорят, что регулярные выражения висполнение My SQL не так уж быстры, а при большом числе страниц, этомедлительность может стать катастрофической
* Метод позволяет обрабатывать URL, построенных абсолютно любым способом, который можно описать при помощи регулярных выраженийПочти все приведённые варианты(кроме 3 и 5) страдают 1 проблемой: они не могут разбирать URL формата: ////и подобныеДобавление слeша в конце
Вводная:
Нужно добавлять слeш в конце URL, если он отсутствует.Решение:RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]ЧПУ при помощи ошибки 404 и POST данные
Вводная:
Сегоднястал детально разбираться с ЧПУ через обработку 404 ошибки. Вроде всезамечательно работает, но вот я не могу получить данные из $_POST.Ответ:
Суть заключается в использовании директивы Error Document? для перенаправления всех несуществующих запросов на один скрипт.
Главный существенный недостаток Error Document? - невозможность перехвата POST-данных!
Чтобы получить POST данные формируйте action формы на реально существующий URL.
Также,к недостаткам относится то, что засоряется error.log сервера, чтомешает выявлению настоящих ошибок, которые необходимо исправить.ЧПУ при момощи Multi Views? или Force Type? Apache Вводная:
Слышал, что существует способ "скрытия" расширения PHP-файлов при помощи конфигурирования непосредственно Apache.Ответ:
Первым является способ с использованием Mutli Views?.
Самспособ заключается в том, что у реальносуществующего файла скрываетсярасширение. То есть до какого-то момента URL реальный, а после - нет.
Он "включается" добавлением в .htaccess или к настройкам сервера:На самом деле, это более понятно на примере.
Допустим, у насесть файл article.php, лежащий в корне Web-сервера. Тогда запросы вида/article/php_security1, /article/sessions будут обрабатываться скриптомarticle.php. Далее, уже всё зависит от разбора в скрипте остальнойчасти URL(если требуется).Второй способ основывается на Force Type?.
Способ позволяет добиться аналогичного эффекта при использовании Force Type?. Мы называем файл просто article, а не article.php.
И в .htaccess или конфигурации сервера добавляем:Так что теперь файл article будет интерпретироваться PHP. Категория: Web технологии | Просмотров: 265