ЧПУ своими руками (PHP). Хранение ЧПУ в базе данных

1 июля 2010
Просмотров: 19666Обсудить
Рубрика: Программирование -> Web -> PHP

В статье ЧПУ своими руками PHP я уже немного рассказал о методе построения ЧПУ. Конечно, тот вариант не сильно привлекателен, если у вас огромный сайт и несколько сотен (а то и тысяч) страниц. Для таких больших проектов стоит применять немного другие методы. В этой статье будет рассмотрен один из них:

Хранение ЧПУ в базе данных

1) Плюсы:

  • Такие урлы доступны в любой точке кода. Просто сделал выборку по какой-то переменной из базы и получили ЧПУ-шный урл.
  • При хранении ссылки в базе можно расширить таблицу и внести туда 3 поля (для мета данных). В таком случае каждому урлу можно руками присваивать title,keywords & description. А это порой очень и очень нужная штука.

2) Минусы:

  • Для каждого товара, для каждой записи на странице будет необходимо обращаться к базе данных за ЧПУ-шным урлом. Думаю любому понятно, что это не есть хорошо. С другой стороны - если реализовать нормальное кеширование самых популярных ссылок - особых проблем (тем более на небольшом магазине) быть не должно.
  • При добавлении какой-то переменной (будь то страница, язык и т.д.) в базе будет создаваться новый урл (ведь исходный был изменен). В итоге, если вы не будете делать необходимых проверок и эту особенность заметят конкуренты - у вас будет вся база данных забита левыми ссылками и, вскоре, просто подохнет.

3) Реализация.

Для начала создайте табличку, в которой будете хранить сгенерированные ЧПУ.

У меня она имеет такой вид:

CREATE TABLE IF NOT EXISTS `pp_sef_links` (
  `link_id` int(11) NOT NULL auto_increment,
  `hits` int(11) NOT NULL,
  `ufu` varchar(255) NOT NULL,
  `link` varchar(255) NOT NULL,
  `mdate` date NOT NULL,
  `status` tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (`link_id`),
  UNIQUE KEY `ufu` (`ufu`),
  UNIQUE KEY `link` (`link`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Видим, что таким образом можно отслеживать обращения к ссылке, включать\выключать ее и т.д.

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

При формировании страницы в месте, где должна быть ссылка будет вызов метода, который вернет ЧПУ

$sef->getUfu("index.php?task=news");

Реализация самого метода зависит от проекта. Это может быть просто набор правил, который по входящим параметрам выдает результат, или набор модулей (для каждого модуля - свой алгоритм). Важно одно: метод должен сначала проверить, нет ли ссылке в базе (если есть - вернуть ее), и если нет - создать новую и запихнуть в базу.

С генерацией и сохранением урлов разобрались. Теперь рассмотрим случай, когда пользователь кликнул по этому самому ЧПУ.

Для того, что новый урл обрабатывать, необходимо 2 вещи:

1) Единая точка входа (один файл, который будет отрабатывать наши ЧПУ, подключать необходимые модули, создавать переменные и т.д.). В моем случае - это index.php

2) Работающий .htaccess файл на сервере и включенный мод_rewrite

Содержимое .htaccess

# включаем мод реврайт
RewriteEngine on
#пишем условия срабатывания - всегда, кроме файлов (реально существующих на сервере)
RewriteCond %{REQUEST_FILENAME} !-f
# и директорый
RewriteCond %{REQUEST_FILENAME} !-d
# перебрасывать все на нашу точку входа, запихнув параметры запроса в переменную sefq
RewriteRule ^(.*)$ index.php?sefq=$1 [L,QSA]

Надо сказать, что sefq - я вообще не использую, вместо этого - проверяю $_SERVER['REQUEST_URI']

Часть кода из index.php, отрабатывающая запрос

if (isset($_SERVER['REDIRECT_STATUS'])) { // если есть редирект
	$url=urldecode($_SERVER['REQUEST_URI']);// отрабатываем урл 
	$url=ltrim($url,"/"); // убираем лишние "/"
	
	if (!$sef->parseURL($url)) { // метод по входящему ЧПУ получает "нормальную" ссылку 
					// и создает необходимые переменные в $_GET
					// если не нашел ссылку - возвращает false
		// error 404;
		$sef->register404($_SERVER); // регистрируем 404 (чтоб потом можно было их чинить)
		$app->notice($langData['_ERROR_404_']);//выдаем пользователю сообщение, что стрнаица не найдена
		header("http/1.0 404 Not found");// ставим соответствующий хеадер
	} else
		header("http/1.0 200 Ok");// ставим соответствующий хеадер
}else { // direct page is ...
		$newUrl=$sef->getUrl($_SERVER['REQUEST_URI']); // пытаемся сформировать ЧПУ по прямой ссылке
		if ($newUrl === false){
			$app->notice($langData['_ERROR_404_']); // если ничего не вышло - 404 ..
			header("http/1.0 404 Not found");
			
		}	
		elseif($newUrl != "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] && $_SERVER['REQUEST_METHOD'] == "GET") {
			header("HTTP/1.1 301 Moved Permanently"); // если все нормально - по 301 редиректу перенаправляем пользователя на новую страницу
			header("Location: ".$newUrl);
			exit;
		}
		
		
}

Плюшки, я дума, вы уже придумаете сами.

В следующей статье я напишу еще более (на мой взгляд) прикольный метод формирования ЧПУ, который наиболее подходит для больших магазинов или высоко нагруженных проектов!

зы: буду рад аргументированной критике.

google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru
Метки: , ,


Комментариев: 6
Подписаться на комментарии по RSS
  • #12011-01-24 в 18:37:18Гарик (анонимно)

    В следующей статье я напишу еще более (на мой взгляд) прикольный метод формирования ЧПУ, который наиболее подходит для больших магазинов или высоко нагруженных проектов!

    И где? cool smile


  • #22011-01-24 в 22:35:33yaap

    @Гарик (анонимно)

    Дык вот же ;)


  • #32011-11-22 в 17:12:07vredin (анонимно)

    подскажи, пожалуйста. я написал галерею с админкой и всеми делами, сделал ЧПУ, но немного по-другому чем ты: в nginx сделал редирект всех ссылок на index.php, в нем разбираю урл на части и через case подгружаю необходимые части шаблона. проблема возникла с rss - не могу придумать как сделать редирект так, чтобы не возникало ошибки "Ошибка синтаксического анализа XML: объявление XML или текста не в начале сущности"


  • #42011-11-23 в 12:41:34yaap

    @vredin (анонимно)

    Гугл решает!

    http://www.eavasi.ru/xml-error/

    http://www.google.com.ua/search?hl=ru&source=hp&aq=1&aqi=g10&aql=&oq=a&gs_rfai=&q=%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0+%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B3%D0%BE+%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0+XML%3A+%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5+XML+%D0%B8%D0%BB%D0%B8+%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B0+%D0%BD%D0%B5+%D0%B2+%D0%BD%D0%B0%D1%87%D0%B0%D0%BB%D0%B5+%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8


  • #52012-02-09 в 11:59:32Роман (анонимно)

    Если в скрипте перенаправлять пользователя на другу страницу с помощью header("Location: ".$newUrl), то в адресе браузера отображается именно $newUrl, т.е. не ЧПУ адрес, а адрес страницы php. Т.е. иными словами "не работает" smile Это только у меня так?

    Я обошел проблему использованием Include_once().


  • #62012-02-09 в 12:42:58yaap

    @Роман (анонимно)

    Странно, потому как header("Location: ".$newUrl) для сервера - это будет новый вызов. Поэтому, даже перенаправив пользователя на урл index.php...., но имея правила для обработки ЧПУ - сервер должен по исходному урлу найти ЧПУ и перебросить (еще раз) пользователя на него.

    В любом случае это плохая практика, почему $newUrl сразу не делать ЧПУшным ?

    У меня для этих целей есть класс $sef, который используется примерно так:

    header("Location: ".$sef->get($newUrl));
    

Оставьте комментарий!

Не регистрировать/аноним

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email.
(При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д.)



grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

(обязательно)