Адрес вашего сайта появляется на пользовательском экране одновременно с дизайном и контентом. Поэтому адрес является полноправной частью сайта. Адрес типа 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);
и потом обрабатывать подстроки по одной (перед взрывом надо убрать из начала и конца строки слэши).
Кстати, перед тем, как писать материал, я честно отправил письмо на info@lenta.ru с вопросом, используется ли у них такой метод обработки запроса или там действительно существуют директории. Мне не ответили. Не буду гадать, как у них сделано, напишу, как бы я делал обработку адреса.
- 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 обязательна!
Оставить комментарий
Вы должны войти, чтобы оставить комментарий.