Skinnable-cacheable
Придумал неболшую идею. Наверняка не я первый.
Идея заключается в том, что страницы кэшируется. Но при этом хочется сделать их Skinnable. То есть чтобы можно было «шкурки» менять. Как кэшировать в таком случае — не совсем понятно.
Простой и забавный (полу)выход. Везде в документах пишем и документы, естественно, кэшируем полностью. И выдаем кэш. А вот css.php — нет, не кешируем и выдаем в нем нужную css-ку в зависимости от содержимого cookies-ов.
ЧПУ и PHP (revisited)
ЧПУ — это термин, придуманный командой НовоКиберска, обозначает он «Человекопонятный УРЛ». Термин нигде широко не употреблялся, пока я не написал 5 сентября 2000 года заметку «ЧПУ и PHP». За эти три года термин довольно неплохо раскрутился.
За эти годы очень многие ссылались на эту заметку, поэтому я взял на себя труд переписать ее, добавив еще несколько способов сделать ЧПУ и убрав всякий мусор. Итак...
В принципе, ничего нового и оригинального в идее понятного УРЛа нет. Про это писал и Лебедев, и другие товарищи. Вообще, мне всегда нравились УРЛы такого, например, вида: php.resourceindex.com/Complete_Scripts/Guestbooks/
Итак, как это сделать в домашних условиях?
Способ раз
Вообще, самая первая мысль — это создавать для каждой заметки поддиректорию с соответствующим именем и помещать в нее index.html, то есть сделать так, чтобы по адресу spectator.ru/technology/php/user_friendly_urls лежал бы реальный файл. Разумеется, так дело не пойдет.
Способ два
Думаем дальше. Раз страница не существует, то она выдает 404. Так что вторая идея — прописать в фале .htaccess страницу, которая будет выдаваться при ошибке 404, а уже эта страница будет смотреть на текущий УРЛ и выдавать нужный документ
То есть, в .htaccess пишем:
------------------------------------
ErrorDocument 404 /index.php3
ErrorDocument 401 /index.php3
------------------------------------
Пользователь набирает spectator.ru/technology/php/user_friendly_urls, такая страница не найдена, и загружается файл index.php3. Дальше — все просто. Переменная $REQUEST_URI дает нам адрес вызываемой страницы (в данном случае это будет /technology/php/user_friendly_urls), вывести на экран соответствующий документ — дело техники.
Этого мало. В некоторых браузерах и с поисковиками такой фокус не пройдет: страница 404 будет выдавать соответствующий код, и страницы индексироваться не будут. Поэтому надо, чтобы страница, которая грузится в случае ошибки 404, изменяла бы код ошибки и сигналила, мол, все ОК, есть такая страница:
Итого: прописываем в .htaccess страницу, которая, собственно, за все отвечает (у меня это index.php3). В этой странице пишем php-скрипт, который работает с $REQUEST_URI, шлет заголовок «http/1.0 200 Ok» и отображает то, что надо.
Плюсы: Очень простой способ. Работает почти везде.
Минусы: При таком способе нельзя постить содержимое формы на несуществующие псевдоурлы. И если в Апаче ведется лог 404-ых ошибок, то он будет забит.
Способ три
Для этих (и не только) целей есть специальный модуль в Апаче, который называется mod_rewrite. Он позволяет «переписывывать урлы», то есть, преобразовывать их «на лету» по правилам, которые вы ему опишите.
Это очень мощный модуль, и если вы в нем разберетесь, то сможете творить чудеса. Сам я до сих пор довольно мало с ним работал, поэтому читайте документацию, благо, что ее полно.
Module mod_rewrite URL Rewriting Engine.
A Users Guide to URL Rewriting with the Apache Webserver.
Модуль Apache mod_rewrite.
Mod_rewrite для чайников.
Плюсы: Очень мощный способ.
Минусы: Может не хватить мозгов. На хостинге может быть не установлен этот модуль.
Способ четыре
Основан на директиве FilesMatch, которая в Апаче является core feature. Все просто. Пишем опять же в .htaccess
Action throw /index.php
ForceType throw
ForceType application/x-httpd-php
После этого все УРЛы, которые подпадают под условие «^([^.]+)$», (то есть все урлы, в которых не содержится точка) будут передаваться на index.php. Вы можете написать свое условие, разумеется.
Подробности: тут, тут или тут.
Плюсы: Простой и удобный способ.
Минусы: Говорят, что для того, чтобы ForceType работал, php должен быть подключен к апачу в виде модуля. Если php вызывается, как обыкновенный CGI — ForceType работать не будет.
Автоопределение кодировки
Задача: текст может быть или в Koi или в Win. Нужно, чтобы он автоматическии переводился в Win, если нужно.
Есть множесто решений, данное претендует на определенную элегантность и, разумеется, на предельную краткость. Текст, естественно, должен быть длиннее 3 букв.
if (substr_count($res, "П")>substr_count($res, "o")) $res=convert_cyr_string ($res, k, w);
Принцип действия, думаю, понятен?.. Не понятен? Думайте...
DOS, если кому надо, добавляется аналогично.
Простое кэширование страниц
Простое кэширование страниц. Для чайников. На PHP.
Кэширование — замечательная вещь. Часто (теперь — почти всегда) страницы на сайтах генерятся динамически. Это теперь модно. Однако же — в реальности — почти всегда страница собирается заново гораздо чаще, чем она изменяется. Грубо говоря, мы опубликовали новый документ, и при каждом обращении к нему он заново считывается, скажем, из базы данных, заново прогоняется через шаблон и прочее и прочее. Мы снова и снова делаем одну и ту же работу.
А можно просто один раз сделать, а потом сохранить результат этой работы. И при каждом запросе выдавать готовый результат, а не делать все заново. Это и есть кэширование.
Оно позволяет, снизить нагрузку на сервер и на базу данных. Непонимание принципов работы кэша иногда приводит к забавным курьезам.
Единственная проблема — это устаревание кэша. Допустим, что данные на странице изменились, а кэш страницы — еще нет, и пользователю будет выдаваться старая версия страницы. Способы борьбы:
1. Выставлять более-менее приемлимое время устаревания кэша. Например, через 10 минут страница устаревает и кэш генерится заново. Минусы: возможна ситуация, когда пользователю 9 минут будет показываться старая страница.
2. Кнопка «очистить кэш». В некоторых системах вообще нет кнопки «очистить кэш», вместо нее есть кнопка «перегенерить сайт целиком». Нажимаем на эту кнопку — и весь сайт генерится в статичные файлы, то есть, фактически, в кэш. Минусы: стрельба по воробьям из пушки. Мы поменяли одну страницу, а перегенерить приходится весь сайт.
3. «Умная» очистка кэша. Очищается только кэш той страницы, которую мы изменили. Минус: часто изменение одной страницы затрагивает и несколько других. Главное — понять, каких именно и очистить кэш у них тоже.
Лично у меня реализованы все три метода.
А теперь — в двух словах, как сделать себе кэш. Чудесные функции PHP — ob_start и иже с ней позволяют не выводить страницу в браузер, а, например, сохранить ее в переменную. Про это я уже писал.
Это вставляем в начале страницы:
$modif=time()-@filemtime ("cache/$crc");
if ($modif<600) ob_start ();$url=$GLOBALS['REQUEST_URI'];
$crc=md5($url);
{
include ("cache/$crc");
exit();
}
Как это работает:
Берем адрес страницы, вычисляем из него md5. Это будет использоваться, как идентификатор страницы. Например, для УРЛа technology/php/caching md5 будет всегда одим и тем же. Этим мы и воспользуемся.
Файлы кэша будут лежать в директории cache. Смотрим, сколько секунд (filemtime) исполнилось файлу с кэшэм данной страницы. Если он не очень старый (меньше 600 секунд) и вообще есть — выводим его (include).
Если нет — то включаем ob_start и продолжаем дальше.
Это вставляем в конец страницы:
$fp = @fopen ("cache/$crc", "w");$cache = ob_get_contents();
ob_end_clean ();
echo $cache;
@fwrite ($fp, $cache);
@fclose ($fp);
Как это работает:
Считываем содержимое буфера (ob_get_contents). Получаем в переменной $cache то, что должно было выводится в браузер. Выводим в бразуер, раз должно (echo).
Записываем содержимое буфера ($cache) в директорию cache в файл $crc.
Все. Теперь при следующем обращении к странице с этим адресом скрипт (смотрите первую часть) будет смотреть, есть ли соответствующий файл в кэше и если он еще не устарел — просто выводить его и прекращать обрабатывать страницу (exit).
Примерно так оно и работает. Таким образом, страница выводится из кэша где-то за 0.001-0.004 секунды. Выигрыш процессорного времени налицо.
Разумеется, я описал только общий принцип, у меня сделано несколько по-другому.