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

Опытным путем было установлено, что PHP устанавливает хидеры запрета кеширования при использовании функции session_start();

Вот пример кода, который реализует кеширвоание конкретного файла (обратите внимание на три функции header(), скидывающих лишние хидеры):

  1. session_start(); // где-то вверху начинается сессия
  2.  
  3. …
  4.  
  5. function cmsCache_control($file, $time) {
  6.   
  7.   $etag = md5_file($file);
  8.   $expr = 60 * 60 * 24 * 7;
  9.   
  10.   header("ETAG: " . $etag);
  11.   header("LAST-MODIFIED: " . gmdate("D, d M Y H:i:s", $time) . " GMT");
  12.   header("CACHE-CONTROL: ");
  13.   header("PRAGMA: ");
  14.   header("EXPIRES: ");
  15.   
  16.   if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
  17.     
  18.     $if_modified_since = preg_replace("/;.*$/", "", $_SERVER["HTTP_IF_MODIFIED_SINCE"]);
  19.     
  20.     if(trim($_SERVER["HTTP_IF_NONE_MATCH"]) == $etag && $if_modified_since == gmdate("D, d M Y H:i:s", $time). " GMT") {
  21.       
  22.       header("HTTP/1.0 304 Not modified");
  23.       header("CACHE-CONTROL: MAX-AGE={$expr}, MUST-REVALIDATE");
  24.       exit;
  25.       
  26.     }
  27.     
  28.   }
  29.   
  30. }
  31.  
  32. …
  33.  
  34. cmsCache_control($_SERVER[SCRIPT_FILENAME], filemtime($_SERVER[SCRIPT_FILENAME]));
  35. //дальше обычный вывод того, что кешируем
* This source code was highlighted with Source Code Highlighter.


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

Единственное дополнение — вместо filemtime() можно также использовать другую произвольную дату, в своем скрипте я использовал дату изменения самого свежего файла.

P.S. Приведенный фрагмент мною был модифицирован, чтобы учитывать сессии, но сам код взят отсюда: http://ru2.php.net/manual/ru/function.header.php#85146, а также http://foxweb.net.ru/texts/43.htm (комментарии товарища antishock).