Адрес вашего сайта появляется на пользовательском экране одновременно с дизайном и контентом. Поэтому адрес является полноправной частью сайта. Адрес типа www.фирма.ру (www.фирма.город.ру), естественно, гораздо лучше, чем www.geocities.com/Gonduras/San-Pedrillio/~наша_фирма, кто спорит. А вот по вопросу понятных человеку адресов внутри сайта общественность четкого консенсуса пока не нашла.
Однако пользователю приятнее было бы видеть адрес типа /services/special/ чем /content.phtml?q=e23908a234cc239b3445127.
Лирическое отступление. Помню, на Интернити-99 мне показали флэш-ролик Hewllett Packard Laser Jet 3100. Через пару недель я вспомнил про него и решил скачать его из дома. Я бы долго бродил в бесполезных поисках по сайту Лексмарк (чего вы смеетесь, это так и было!), если бы не их адреса. На HP адреса были понятные — что-то вроде "/products/printers/laserjet/3100", а на сайте Лексмарка было вот именно это непонятное "q=492898748273". Я был в сомнениях, но через день вспомнил-таки, что это был HP :).
Кстати, на этом сайте адреса выпусков, версий для печати и всех информационных страниц (ссылки, файлы и т.д.) виртуальные, файлов с такими названиями не существует.
Делается это достаточно просто. В файле .htaccess пишутся строчки, например
ErrorDocument 404 all.php
ErrorDocument 403 all.php
ErrorDocument 401 all.php
Файл all.php обрабатывает переменную $REQUEST_URI и, если нужная информация найдена, выдет команду
header ("HTTP/1.0 200 Ok");
Это необходимо для того, чтобы броузер IE 4 считал, что страница найдена, а не подставлял вместо нее свою служебную вывеску "адрес не найден". В остальных случаях, даже если запрошен адрес "all.php", пользователю будет выдаваться сообщение о том, что файл не найден.
Если при вызове функции header сервер ругается матом "Error 500" - смотрите здесь и здесь.
Конечно же, выдать заголовок и нарисовать страницу — нехитрое дело. Отслеживание результатов запросов, проверка на ошибки — это скорее рутина. Самое ответственное дело — разбор запрашиваемого адреса.
Тут приемов много. Например, у меня версия для печати и страница отзывов ищутся по регулярным выражениям:
if (preg_match("/(d+)-comment/A", $url, $res)) ...
А потом из переменной $res[0] беру номер выпуска и проверяю наличие его в базе. Адрес из нескольких поддиректорий можно, например, при помощи взрыва :)
$dir = explode("/", $url);
и потом обрабатывать подстроки по одной (перед взрывом надо убрать из начала и конца строки слэши).
Кстати, перед тем, как писать материал, я честно отправил письмо на [email protected] с вопросом, используется ли у них такой метод обработки запроса или там действительно существуют директории. Мне не ответили. Не буду гадать, как у них сделано, напишу, как бы я делал обработку адреса.
if (preg_match("/([a-z]+)/(d{4})/(d{2})/(d{2})/([a-z]+)/A", $url, $match)) { $request = "SELECT news_id FROM news, rub WHERE news.rub_id=rub.rub_id AND rub_address='". $match[1]. "' AND news_date LIKE '". $match[2]. "-". $match[3]. "-". $match[4]. "' AND news_address='". $match[5]. "'";
Этот запрос делается просто для проверки, есть ли такая новость в базе. А потом в зависимости от результата выдается либо страница с новостью, либо какая-нибудь ругань (или главная страница рубрики/сайта).
А вот как я проверяю адреса на этом сайте:
if (preg_match("/(d+)-print/A", $url, $res)) { // версия для печати } elseif (preg_match("/(d+)-comment/A", $url, $res)) { // все отзывы } elseif (!preg_match("/D/", $url)) { // полная версия выпуска } else { // либо остальные рубрики, либо адрес не найден };
Кстати, у себя я как честный человек выдаю header("HTTP/1.0 200 Ok") только если выпуск/рубрика найдены.
И еще один пример. Допустим, рубрики сайта построены как дерево, а таблица в базе выглядит так:
CREATE TABLE rubrika ( id TINYINT NOT NULL AUTO_INCREMENT, parent_id TINYINT, address VARCHAR(16) NOT NULL, title VARCHAR(128) NOT NULL, rub_text TEXT NOT NULL, PRIMARY KEY (id), UNIQUE address (address) );
Что такое title и rub_text — объяснять не надо. Поле address — это адрес, по которому будет запрашиваться рубрика (новости нужно сделать рубрикой первого уровня, и в поле address будет "news"). Поле parent_id — идентификатор рубрики уровнем выше.
Теперь, если рубики заведомо не могут быть ниже второго уровня, анализ адреса не составит особого труда.
$url = $REQUEST_URI; // убираем слэши из начала и конца адреса $url = ereg_replace("^/", "", $url); $url = ereg_replace("/$", "", $url); $dir = explode("/", $url) // случай, когда запрошена рубрика второго уровня. if (sizeof($dir)==2) { // составляется запрос, объединяющий таблицу rubrika саму с собой. //Здесь надо заметить только, что таблица first подразумевает рубрику второго уровня, //а second, наоборот, первого. $request = "SELECT first.id, first.title, first.rub_text FROM rubrika first, rubrika second WHERE first.parent_id=second.id AND first.address='". $dir[1]. "' AND second.address='". $dir[0]. "'"; // Отправляем запрос в базу, а потом обрабатываем результат. $result = mysql_query($request); if (!mysql_error() && @mysql_num_rows($result)==1) { } // Это на случай, если запрос прошел успешно, но ничего не найдено elseif (!mysql_error()) { } // ...и на случай, если произошла ошибка. else die ("Ошибка БД. MySQL пишет: ". mysql_error()); } // Запрошена рубрика первого уровня. тут и делать-то нечего :) elseif (!ereg("/", $url)) { $request = "SELECT id, title, rub_text FROM rubrika WHERE address='$url'"; ... };
Хватит примеров? Дальше — дело фантазии. Подведем итоги, распишем положительные и отрицательные моменты.
Плюсы
Красивые адреса, возможность зайти в рубрику, набрав ее адрес на клавиатуре. Благодарность от фанатов клавиатуры.
Уменьшение количества файлов, уменьшение количества повторяющихся операций в разных файлах.
Централизация вывода. Сбор большинства операций в единой точке входа.
Скрытие некоторой технологической части сайта.
Минусы
Увеличение ресурсоемкости за счет проверки адреса и компиляции большого файла вместо нескольких маленьких.
Сложность с введением новых параметров (я, можно сказать, удачно вывернулся с версией для печати, но было бы более логично видеть адреса типа /13/print). Кое-что придется сбрасывать, например в куки.
Кое-что, например, поиск, так и останется вне "точки входа" (хотя... "How IT works" делает поиск в адресе, но для более-менее сложного сайта это будет неудобно или невозможно).
Дополнительные сложности с адресами картинок и навигации по сайту (броузер-то мерит все адреса относительно открытого документа, пусть даже из несуществующего адреса).
Напоследок: в этом выпуске я использовал кучу регулярных выражений, поэтому (и по просьбам читателей) обещаю в скором времени затронуть эту тему.
Постоянные ссылки
При копировании ссылка на TeaM RSN обязательна!
Оставить комментарий
Вы должны войти, чтобы оставить комментарий.