Статьи

Кэширование страниц PHP с буферизацией вывода

Заметили, что ваши страницы загружаются медленно или просто не любят использовать дополнительные циклы ЦП, когда это не нужно? PHP делает кэширование очень простым благодаря разнообразным функциям управления выводом. В этой статье я рассмотрю полное кэширование страниц, которое проще всего реализовать и понять.

Одна из причин, по которой я люблю PHP, заключается в том, что есть функция для всего. А если нет, то нетрудно найти человека, который его создал для вас. В противном случае PHP, вероятно, дал вам отличный старт в написании своего собственного. Это в случае с функциями управления выводом PHP . Некоторые утверждают, что это слабость PHP, но это уже другая статья.

Концепция кеширования страниц очень проста для понимания. Основная идея заключается в том, чтобы взять сгенерированную страницу, которая выполняет много операций, таких как вызовы базы данных, циклы и т. Д., И сохранить выходные данные где-то, например, в файловой системе. Таким образом, в следующий раз, когда кто-то запросит одну и ту же страницу, мы сможем захватить и отобразить вывод, не прибегая к выполнению одних и тех же запросов и вычислений в одной и той же базе данных снова и снова.

Обзор выходной буферизации

Понять, как работает буферизация вывода, достаточно просто. Есть 3 основных функции, с которыми вы захотите ознакомиться:

<?php
ob_start(); // Turns on output buffering
?> 

 

С момента вызова ob_start () любой вывод будет сохранен во внутреннем буфере PHP и еще не выведен на экран. Это включает в себя HTML и эхо или печатные операторы php. Операторы заголовка являются исключением, поскольку они все еще отправляются в браузер.

<?php
// Stores the contents of the buffer in a variable as a string
$contents = ob_get_contents();
?> 

 

ob_get_contents () вернет строковое значение текущего содержимого буфера. Это окажется очень полезным для целей кэширования при размещении в конце страниц. Подробнее об этом чуть позже.

<?php
ob_end_flush(); // Turn off buffering and print the contents
?> 

 

ob_end_flush () напечатает все содержимое буфера так, как вы ожидаете увидеть, если буферизация вывода никогда не была включена.

 

Кеширование страниц

Вы, вероятно, уже можете догадаться, как использовать эти 3 функции для создания некоторых функций кэширования страниц, так как все основы были представлены, но есть еще несколько дополнительных вещей, которые еще не были рассмотрены. Кэширование страниц обычно делится на 2 блока кода. Большая из которых находится в самом начале каждой страницы, которая устанавливает некоторые переменные, выполняет некоторую проверку и решает, какой путь лучше всего выбрать. Последний находится в самом конце страницы и сохраняет любой контент, который считается нормальным, для кэширования в файловую систему.

Другое дело, что для целей этой статьи я сохраняю весь кэшированный контент в файловую систему, но его можно легко преобразовать в базу данных или в другое хранилище. А пока давайте будем простыми.

Итак, давайте начнем с первого блока кода, который будет размещен в верхней части страницы:

<?php
  $cache_time = 3600; // Time in seconds to keep a page cached
  $cache_folder = '/cache'; // Folder to store cached files (no trailing slash)
  $cache_filename = $cache_folder.md5($_SERVER['REQUEST_URI']); // Location to lookup or store cached file
  //Check to see if this file has already been cached
  // If it has get and store the file creation time
  $cache_created  = (file_exists($cache_file_name)) ? filemtime($this->filename) : 0;
  
  if ((time() - $cache_created) < $cache_time) {
    readfile($cache_filename); // The cached copy is still valid, read it into the output buffer
    die();
  }
?>

Здесь происходит довольно много вещей. Первый блок кода — это просто набор переменных конфигурации.

Возможно, $ cache_folder должен использовать относительный путь, поскольку не все веб-хосты поддерживают корень документа.

$ _SERVER [‘REQUEST_URI’] — это просто запрашиваемая страница и все параметры, которые были отправлены. Мы md5 это, чтобы обеспечить уникальное имя файла. Пример строки, возвращаемой из $ _SERVER [‘REQUEST_URI’]:

<?php
// Let's say our current URL is http://www.domain.com/directory/file.php?id=42
echo $_SERVER[REQUEST_URI]; // prints '/directory/file.php?id=42'
?> 

 

Для $ cache_created задано время (метка времени UNIX), в течение которого был создан последний файл кэша для этой страницы. Если это не удается, установите его на 0.

Оператор IF проверяет, находится ли кэшированный файл все еще в пределах установленного ограничения времени, имеет ли значение true, затем захватывает кэшированное содержимое, сохраняет его в буфере и закрывает страницу. exit () и die () автоматически вызывают ob_end_flush (), поэтому автоматически выводится буферизованный вывод. Если файл не найден или время истекло, начните буферизацию вывода с помощью ob_start ();

С этого момента давайте предположим, что мы планируем кэширование страницы. Все, что находится после этого начального блока кода, будет сохранено в выходном буфере. Последний шаг — добавить некоторый код в самый конец этого файла, чтобы сохранить буферизованное содержимое в файле кэша, который будет использоваться при следующей загрузке этой страницы.

<?php
file_put_contents($cache_filename, ob_get_contents());
ob_end_flush();
?>

Коротко и сладко. На данный момент мы уже знаем, что единственный способ проникнуть так далеко на страницу — это если все другие требования к кешированию не были выполнены, и нам нужно сохранить новую копию в файловой системе. Мы делаем это просто вызывая file_put_contents () и сохраняя содержимое буфера через ob_get_contents () .

 

Что нужно учитывать

Прежде чем приступить к кешированию всего сайта, важно подумать о том, к каким страницам вы хотите применить этот метод. Статические HTML-страницы, вероятно, не увидят какого-либо повышения производительности, поскольку нет необходимости выполнять какие-либо вычисления или выполнять вызовы базы данных, и на самом деле это, вероятно, замедлит работу, поскольку придется вызывать интерпретатор PHP. Страницы списков и подробностей, управляемые PHP, на которых содержимое, по большей части, остается неизменным, но каждый раз собирается из базы данных, идеально подходят для кэширования.

Например, если вы ведете блог и хотите кэшировать свою главную страницу со списком ваших новых записей, это, вероятно, отличная идея. Однако, когда вы публикуете новую историю, вы можете не увидеть ее сразу на первой странице. Чтобы обойти это, просто удалите все файлы в вашем каталоге кеша.

Страница, которую я бы не использовал, это страница, которая часто обновляется, и время имеет существенное значение. Например, это ужасная идея — кэшировать страницу с ценами на акции для аудитории биржевых брокеров, где каждая секунда имеет значение. Другой пример того, когда не нужно кэшировать страницу, — это когда контент передается определенному пользователю. Например, панель инструментов должна иметь до последней информации, и только несколько пользователей будут запрашивать ее.

Конечно, есть исключения из этого правила и много других сценариев, но их слишком много, чтобы их здесь освещать. Просто используйте немного здравого смысла и продумайте вещи до конца.