Простой способ кэширования сайта на стороне сервера

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

Нам понадобятся функции:
file_exists() - проверяет наличие указанного файла или каталога.
readfile() - позволяет прочитать данные из файла. Т.е. эта функция будет читать наш статичный файл
ob_start() - включает буферизацию вывода. Т.е. все, что будет происходить после этой функции, будет сохранено в буфер(временное хранилище)
ob_get_contents() - получает содержимое буфера вывода.
ob_end_flush() - отправляет содержимое буфера вывода пользователю (если оно имеется), очищает его и выключает буферизацию вывода.
fopen - открывает файл или URL
fwrite() - записывает содержимое в файл.
fclose() - закрывает файл.
На сервере предварительно создадим папку caсhe (название можно придумать любое допустимое)

Итак, приступим:
1. В самом начале нашей php - страницы пишем:

<?php
if (file_exists('cache/index_'.$_GET["page"].'_'.$_GET["id"].'.cache')){  
readfile('cache/index_'.$_GET["page"].'_'.$_GET["id"].'.cache'); exit();}
ob_start(); // далее идет любой ваш html-php код include("includes/bd.php"); <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> и т.д. и т.п. ?>

Если у нас существует файл index_xx_yy.cache, то просто считываем содержимое файла, выводим на экран и останавливаем какие-либо дальнейшие действия на странице. Здесь xx - это значение переменной $_GET["page"] (например номер страницы), уу - это значение переменной $_GET["id"] (например какой-то параметр, формирующий нашу страничку). Если же нет, в папке кэш нашей статичной копии включаем буфер и записываем в него все, что происходит на странице.


2. В самом конце после тэга </html>:

<?php  $buffer = ob_get_contents();
ob_end_flush(); 
$fp = fopen('cache/index_'.$_GET["page"].'_'.$_GET["id"].'.cache', 'w'); fwrite($fp, $buffer); fclose($fp);

Мы записываем в $buffer содержимое буфера, после останавливаем буферезацию и очищаем его. Затем открываем файл index_xx_yy.cache // (если его нет на сервере, то создаем, за это отвечает параметр 'w' у ф-ции fopen), записываем в файл $fp значение $buffer и закрываем его. Теперь у нас php - страница будет обрабатываться на сервере 1 раз с первым посетителем, а для всех последующих выводить статичный html- код.
Что будет если параметров $_GET["page"] и $_GET["id"] не существует?
(если загружена страница index.php без переменных $_GET). Файл index_xx_yy.cache примет вид index__.cache (после index двойная черта), что в принципе является нормальным именем файла :)

 

3. Теперь о том, как очистить кэш. Это необходимо когда вы добавили что-то новое на страницу или на сайт, у вас появилась новая запись в гостевой. Просто добавьте в нужном месте (например после того, как запись в гостевой была добавлена в базу данных):

unlink ('cache/index_'.$_GET["page"].'_'.$_GET["id"].'.cache');

Эта функция удалит кэш файл index_xx_yy.cache

Помните:
Папка cache должна быть доступна на запись. Если предполагается выводить какие-то случайные заметки , стоит проводить буферизацию блоками и подключать БД к страничке до включения буферизации, т.е. вы должны определить что должно кэшироваться и кэшировать только нужные участки, создавая файлы в папке кэш с названием ваших блоков. В принципе тоже ничего сложного, если вы поняли это урок, сделать блочную буферизацию не составит большого труда.

Вот и все, что требуется для простейшей реализации кэширование сайта на стороне сервера. Всем удачи, коменты приветствуются.

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: phpwiki.ru
Перевел: Евгений Стыценков
Урок создан: 22 Апреля 2009
Просмотров: 48379
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

    Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

    Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 22 Апреля 2009 19:18
    dima
    если движок на тектовых файлах то очень даже полезно применить..)) в гостевых на текстовых файлах такое видел =)
  • 22 Апреля 2009 19:23
    Дмитрий
    Очередная полезность... Ждём ещё...
  • 22 Апреля 2009 19:46
    AlexGrin
    Наконец-то и PHP пошло!
  • 22 Апреля 2009 23:42
    Aleshka
    Для администрации сайта это хорошо пойдет, это единственное что я хотел узнать про кэширование файлов. Теперь можно спокойно создавать администрационный раздел :)
  • 23 Апреля 2009 07:25
    dima
    сделал в гостевой, но чуток подругому)), Вместо проверки для чтения файлов с $_GET параметрами в cache/ , я просто сохранял содержимое извлеченное из $GLOBALS["REQUEST_URI"]; в переменную $url и выводил кэш-контент если время его существования меньше 600секунд. источник: http://spectator.ru/technology/php/caching да, и незабудьте удалить из мета тэгов запрет кэширования, если есть: <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
  • 23 Апреля 2009 07:27
    dima
    Евгений, несколько вопросов: 1)эффективно ли использовать такое кэширование в случае извлечения контента исключительно из базы данных mysql? 2)на счет параметров $_GET, это получается нужно проверять все используемые в скрипте get-параметры?, т.е. $_GET["cat"],$_GET["id"],$_GET["page"] и так далее. И как например быть с POST-переменными, которые передаются через форму? например в случае добавления комментариев на страничку. 2)На счет 3-го пункта можно поподробней? куда конкретно вставить эту строчку(очистка кэша), ведь большинство операций по внесению материалов на сайт осуществляется через админ.скрипты. И ещё хотелось бы увидеть практический пример про блочную буферизацию. спасибо)
  • 23 Апреля 2009 09:53
    yaЕвген
    Для Дима. http://okonnaya-palitra.ru/ - реализовано. все что извлекается из БД выводится на сайт и соответственно записывается в кэш. По поводу Get - переменных. Проверять их надо в любом случае, независимо есть ли кэширование или нет. По вопросу по тому как удалить нужную страницу из кэша: В форме коментариев в скрытых полях можно : <input value="$_GET["cat"]" name="cat" type="hidden"> и т.д. а уже в обработчике после добавления комента в БД поставь строчку из п.3, только естесственно немного изменив unlink ('cache/index_'.$_POST["page"].'_'.... и т.д. Т.к. в приведенном выше сайте не подрузамевается ежедневное обновление контента, там я вообще очищаю весь кэш при выходе из админки, т.е. зашел, чего то сделал, уходя почистил все
  • 23 Апреля 2009 10:33
    dima
    не не, у меня через форму переменные передаются только методом POST ))) вообще я узнал вроде как post-переменные не кэшируются вопще(( я уже нашел универсальный способ с использованием настроек в .htaccess, хотя в нем тоже есть свои недостатки(, но нужно попробовать все варианты и наиболее эффективный оставить.спасибо)
  • 23 Апреля 2009 11:39
    yaЕвген
    dima, ты меня не понял ))
  • 23 Апреля 2009 11:59
    yaЕвген
    dima, сделай так <input value="<?php echo $_GET["cat"] ?>" name="cat" type="hidden"> вот)) и у тебя в инпуте будет значение переменной $_GET["cat"] , которая и улетит постом и в обработчик как POST придет
  • 23 Апреля 2009 12:43
    dima
    я понел, но мне так ненадо... у меня и так этот идентификатор записи передается и адресную строку и через POST. К тому же через форму get параметры лучше не передавать имхо небезопасно. зы: я просто хотел сказть к тому, что нельзя делать unlink(('cache/index_'.$_POST["id"].'.cache');, т.е это работать не будет. только GET!)
  • 23 Апреля 2009 13:47
    dima
    кстати, вызов сессии должен быть до начала кэширования
  • 24 Апреля 2009 21:00
    Святослав
    Что-то я чуть чуть запутался: Как записать данный код, если помимо страниц index, есть еще about_us, magasin, blog, wiev_cat ???
  • 25 Апреля 2009 12:20
    yaЕвген
    так и пиши. wiev_cat_'.$_GET["page"].'_'.$_GET["id"].'.cache') на странице wiev_cat.php Далее аналогично
  • 25 Апреля 2009 15:26
    dima
    да лучше не ставить это кэширование, особенно для динамических страничек, тока лишний код будет и проблемы с авторизацией(если она есть на сайте). Вот для статических страничек типа: контакты или about.php это пойдёт, а для блога с постоянным обновлением контента некатит((. Единственное, для чего можно сделать кэширование - это для статических шаблонов, формирующих дизайн страниц, но это уже блочная буферизация. кому интересно, вот ссылка => http://www.htmlweb.ru/php/php_cache.php
    • 21 Июля 2012 19:01
      truehazard
      ну да ну да, а о нагрузках на сервер что нибудь слышали ? когда в базе >500 000 записей как тогда будет вести себя сервер отдачи когда вы захотите вытянуть скажем 200 000 запись, просто нужно грамотно его использовать (обновлять) и прочее.
  • 22 Июня 2009 00:51
    Мухаммад
    Супер
  • 12 Июля 2009 18:35
    Rentik
    О, прикольно, я в одной книжке про такой трюк читал. Очень полезная вещь учитывая, что у многих в России интернет ещё Dial-up.
    • 14 Апреля 2012 16:31
      gaaarfild
      Причем тут диалап? Он не сокражает количество контента. Он уменьшает нагрузку на сервер.
  • 23 Марта 2010 09:28
    виктор
    А вот как запретить кэширование на компьютере пользователя, хотя бы одну страничку?
  • 2 Октября 2010 14:38
    xand
    Евгений на своих сайтах вы используете такой метод кэширования?
  • 21 Июля 2012 19:03
    truehazard
    Немного спорный вопрос, после того как содержание записалось в файл, зачем вы открываете только что созданный файл, и только потом выводите его ? если можно просто после того как запись произошла вывести переименую $buffer
  • 22 Февраля 2013 18:58
    messi10
    Если создал новую категорию для статьи, то ссылка на новую категорию должна появиться на всех страницах, а по Вашему получается она не появиться на тех страницах где уже есть кэш. как в этом случае очистить весь кэш. И не зависнет ли сервер если в кэшэ очень много файлов?
^ Наверх ^