Буферизация вывода для кэширования PHP-файлов
Перво-наперво, поблагодарим Dennis Pallett за его PHP-код (ссылки внизу), благодаря которому были развеяны мифы буферизации вывода. Код, что вы увидите в этом уроке, адаптирован из его скрипта с небольшими изменениями, дабы сделать его более подходящим, особенно под Linux/UNIX системы.
1. Создание файлов Кэша с использованием буферизации вывода.
Принципиальное отличие такого типа буферизации это то, что вы генерируете страницу как обычно, используя PHP, но кэшируемые значения хранятся в памяти, вместо того, чтобы отправляться непосредственно в браузер. Это даёт шанс для ленивых программистов отправлять некоторое количество новых header-заголовков, однако, благодаря этому же становится возможным записать кэшируемые значения из памяти в файл.
Логика нижеследующего скрипта, который вы можете просто подключить в верхнюю часть страницы, выглядит следующим образом.
- Если кэшируемая версия страницы существует и она не слишком старая, то отобразить файл и выйти - cache_display();
- В противном случае записать выходные значения в файл и отобразить их в браузере - cache_page()
<?php
// Адаптировано для CodeHarmony.ru
// Основано на коде Dennis Pallett: www.phpit.net
// Пожалуйста включите данные комментарии если вы будете использовать нижеследующий код
// префикс и местоположение файлов кэша
define('CACHE_PATH', "/tmp/cache_");
// как долго хранить кэшируемые файлы, в часах
define('CACHE_TIME', 12);
// вернуть местоположение и название кэш-файла
function cache_file()
{
return CACHE_PATH . md5($_SERVER['REQUEST_URI']);
}
// отобразить кэш, если его "срок годности" не истёк
function cache_display()
{
$file = cache_file();
// проверка, что кэш-файл существует и он не слишком старый
if(!file_exists($file)) return;
if(filemtime($file) < time() - CACHE_TIME * 3600) return;
// если всё ок, то отобразить кэш-файл и прекратить дальнейшие проверки
readfile($file);
exit;
}
//запись в кэш-файл
function cache_page($content)
{
if(false !== ($f = @fopen(cache_file(), 'w'))) {
fwrite($f, $content);
fclose($f);
}
return $content;
}
// выполнение прекращается, если был найден валидный (исправный) кэш-файл
cache_display();
// активировать внешнюю буферизацию и создать кэш-файл
ob_start('cache_page');
?>
Сохраните этот скрипт как buffer.php и включите функцией include его в самом верху ваших HTML/PHP файлов.
Этот скрипт предполагает наличие директории /tmp/, у которой установлены права на запись файлов со стороны веб-сервера. Если это не так, или вы хотите хранить кэш-файлы в другом месте, вам нужно создать каталог с правами на запись файлов со стороны веб сервера (chgrp для пользователя веб-сервера и chmod 775) и соответствующим образом изменить константу CACHE_PATH.
Также предполагается, что определена переменная $_SERVER['REQUEST_URI'], что не всегда так, особенно на платформах работающих под Windows XP или Microsoft IIS. Посмотрите комментарии пользователей в PHP-документации в разделе предопределённые переменные чтобы разобраться с этим моментом.
2. Как использовать данный скрипт?
Вам нужно подключить этот скрипт до вывода какого-либо контента на странице. Последующий html- и PHP-код будет доступен как только поступит необходимость обновить кэш-файл (первый раз в самом начале, и далее каждый кэшируемый интервал - константа CACHE_TIME).
Несколько вещей, о которых вам нужно знать, если вы хотите использовать скрипт на живом сайте:
1. Убедитесь , что вы исключили все блоки и секции, отвечающие за динамический вывод информации.
2. Убедитесь, что CMS (система управления контентом), которую вы используете, знает как удалить текущий кэш, в противном случае вы будете ждать часами чтобы увидеть какие-либо изменения на сайте.
Преимущество использования директории /tmp/ для хранения кэш-файлов в том, что сервисы, такие как tmpreaper могут автоматически чистить любой мусор, оставляемый вашим сайтом, при изменении его структуры или при удалении страниц.
С другой стороны, вы можете использовать следующую функцию, чтобы удалить кэш.
<?php
function cache_remove($path)
{
$file = CACHE_PATH . md5($path);
if(file_exists($file)) unlink($file) or die("Could not remove file: $file!");
}
?>
3. Преимущества от использования буферизации вывода перед другими методами
Красота этого решения в том, что оно полностью независимо от того, каким методом вы генерируете контент. Как бы страницы ни создавались - вручную, с помощью CMS или сторонним ресурсом - нет никакой разницы. Даже схема адресации не имеет значения.
Другое преимущество, в том, что кэш можно удалить в любой момент, не повлияв тем самым на сайт. В конце концов, весь скрипт - это всего 20 строк кода!
Этот метод кэширования сильно контрастирует с другими, например с теми, что генерируют некоторые CMS. Они создают PHP-файлы, которые являются ужасно запутанными и сложными, а затем парсятся и обслуживаются браузером.
Если это единственный способ для генерации нового контента или изменения текущего, то в дальнейшем это здорово усложняет внесение каких либо даже простейших изменений.
Альтернативное решение - создать статическую версию динамического сайта с ЧПУ url-адресами, которая будет "отдаваться" браузере с того же самого или с другого сервера. Опять же, как веб мастер вы должны удалять накопившийся кэш перед обновлением контента.
4. Архивируемый кэш
Также давайте посмотрим, как можно хранить закэшированный контент в заархивированном виде. Это значит, что мы архивируем контент как только он попадает в каталог для КЭШа и разархивируем перед выводом на экран.
Большинство серверов и браузеров поддерживают отправку HTML/text данных в формате gzip, но это не то, о чём идёт речь здесь. В этом случае данные будут храниться в заархивированном виде, но отправляться будут как HTML/text. Доставка архивированного контента требует дополнительной работы.
<?PHP
// Адаптировано для CodeHarmony.ru
// Основано на коде Dennis Pallett: www.phpit.net
// Пожалуйста включите данные комментарии если вы будете использовать нижеследующий код
// префикс и местоположение файлов кэша
define('CACHE_PATH', "/tmp/cache_");
// как долго хранить кешируемые файлы в часах
define('CACHE_TIME', 12);
// вернуть местоположение и название кэш файла
function cache_file()
{
return CACHE_PATH . md5($_SERVER['REQUEST_URI']);
}
//отобразить кэш если его "срок годности" не истёк
function cache_display()
{
$file = cache_file();
// проверка что кэш-файл существует и он не слишком старый
if(!file_exists($file)) return;
if(filemtime($file) < time() - CACHE_TIME * 3600) return;
// если всё ок, то отобразить кеш-файл и прекратить дальнейшие проверки
echo gzuncompress(file_get_contents($file));
exit;
}
//запись в кеш-файл
function cache_page($content)
{
if(false !== ($f = @fopen(cache_file(), 'w'))) {
fwrite($f, gzcompress($content));
fclose($f);
}
return $content;
}
// выполнение прекращается, если был найден валидный(исправный) кеш-файл
cache_display();
// активировать внешнюю буферизацию и создать кеш файл
ob_start('cache_page');
?>
Это значительно уменьшит «вес» директории с кэшем, однако вместе с тем создаст дополнительную нагрузку на сервер для архивации и разархивации контента.
Опять же, это не то же самое, что gzip-компрессия, которая включает часть информации из header-заголовков.
5. Ссылки
Как создать простую систему кеширования с помощью PHP
PHP.net: Функции контроля вывода
Материал подготовил Денис Малышок специально для сайта CodeHarmony.ru
P.S. Хотите двигаться дальше в освоении PHP? Обратите внимание на премиум-уроки по различным аспектам сайтостроения, включая программирование на PHP, а также на бесплатный курс по созданию своей CMS-системы на PHP с нуля. Все это поможет вам быстрее и проще освоить этот мощный язык веб-разработки:
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также:


















