Пожалуйста, помогите с системой кеширования на сайте

Spear

почемучка
Пожалуйста, помогите с системой кеширования на сайте

Здравствуйте,
у меня такая проблема - все никак не разберусь с српавлиьной настройкой кеширования сайта.
сайт на РНР. я с хедерами вообще запутался.

Подскажите, пожалуста, правильо ли я делаю кеширование
PHP:
$if_modified_since = preg_replace('/;.*$/', '', $HTTP_IF_MODIFIED_SINCE);

$mtime = filemtime($SCRIPT_FILENAME);
$gmdate_mod = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

if ($if_modified_since == $gmdate_mod) {
    header("HTTP/1.0 304 Not Modified");
    exit;
}
header("Last-Modified: $gmdate_mod");
больше НИКАКИХ хедеров я не отправляю. Правильно делаю?
нужно чтобы юзер мог кешировать страницы, но если на них обновление - чтобы она обновлялась. И чтобы работало во всех браузерах.
\Буду очень благодарен. Ато сейчас жалобы - у некоторых вообще е обновляются страницы, а и чтобы увидеть обновления нужно почистить кеш браузера.

-~{}~ 08.07.05 06:30:

ещё появилось нескольковопросов (всю ноь о кешировании думаю)
что значит кешировнаие на стороне сервера?
генерацию файлов, и выдачу их юзеру, если файлы не старше чем.... да?

вот статья:
http://phpclub.ru/faq/wakka.php?wakka=TekushhiePopolnenija/PerevodHTTPCaching/CaptureServerSideOutputForCaching&v=110m

последний пример (Блочная буферизация) мне очень понравился. Используют ли такое на очень крупных сатах, с огромной посещаемостью?
насторожила фраза в статье:
В этом примере я использовал процедурный подход. Однако я не советую делать это на практике, поскольку это закончится очень грязным кодом (смотри последующие решения с лучшей альтернативой) и, вероятно, вызовет проблемы с блокировкой файла (например, что случится, когда кто-то обращается к кэшу в момент его обновления?).
Я не понял автора. То есть приведенный код лучше не использовать? тогда как же делать?

очень надеюсь на ваши ответы, т.к. хочу оптимизировать свой сайт по максимуму.
 

SiMM

Новичок
> То есть приведенный код лучше не использовать?
Т.е. приведённый код является лишь демонстрацией того, как нужно делать, поясняющим принципы. И он написан предельно просто, чтобы любому было понятно, что и как, без всяких ООП-извратов, которые непосредственно к самому кэшированию отношения никакого не имеют и являются лишь стилем программирования.
 

Spear

почемучка
у меня такая проблема (с кешированием у пользователей):

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

$if_modified_since = preg_replace('/;.*$/', '', $HTTP_IF_MODIFIED_SINCE);

$mtime = filemtime($SCRIPT_FILENAME);
$gmdate_mod = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';

if ($if_modified_since == $gmdate_mod) {
header("HTTP/1.0 304 Not Modified");
exit;
}
header("Last-Modified: $gmdate_mod");

И чтобы увидеть обновления нужно очищать кеш раузера. Может это глюк браузера? хотя не похоже.. я его уже переустановил даже.
 

ksnk

прохожий
Вот то, что у меня работает... Может чем-то поможет...
Проверялось на броузерах IE, FF, Opera 7.50
PHP:
   function CheckModyfied($fname,$etag=NULL)
  {
    // функция корректно выставляет хидеры времени-етага, 
    // и заодно проверяет - а оно нам действительно надо или таки нет

    $t=filemtime(__FILE__);
    if ($fname) $t=max( (file_exists($fname))?filemtime($fname):-1,$t);

    $lastmod=gmdate("D, d M Y H:i:s",$t)." GMT" ;
    $headers = apache_request_headers();
    $can_generate = true;

    if (isset($headers["If-Modified-Since"]) || isset($headers["If-None-Match"])) { // oops!
      $can_generate = false;
      if (isset($headers["If-Modified-Since"]) ||($fname))  // oops!
         $can_generate = $can_generate || ($lastmod !=$headers["If-Modified-Since"]) ;
      if (isset($headers["If-None-Match"]) ||($etag))  // oops!
         $can_generate = $can_generate ||  ($etag!=$headers["If-None-Match"]) ;
    }
    if (!$can_generate)      {
        header("HTTP/1.1 304 Not Modified") ;
        exit();
    } else {
       header("Last-Modified: " .$lastmod);
       if($etag) header('ETag: "'.$etag.'"');
    }
  }
  header("Content-type: image/jpeg");
  CheckModyfied($fname);
 

kruglov

Новичок
Там еще заголовок Cache-Control: max-age=секунды бывает, можно его изучать. А то иногда браузер и запрос-то не делает, а сразу берет из кэша.
 

Spear

почемучка
$t=filemtime(__FILE__);
а если у меня страницы вида
junp.php?nav=10? (новости, напоример). Работать будет?
 

Spear

почемучка
посмотрите, пожалуйста, может я что не то с хедерами сделал...
Хедеры. Сначала зашёл на страницу, потом в другой окне её изменил (через админку. Название статьи поменял на "ТЕСТ") - но всеравно браузер грузит страрую версию. Обновления страницы, закрыотие и открытие браузера и т.п. - не помогло.

GET /art/2 HTTP/1.1
Accept: */*
Referer: http://www.test.com/art/
Accept-Language: ru
Accept-Encoding: gzip, deflate
If-Modified-Since: Tue, 21 Jun 2005 20:22:02 GMT; length=54752
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; URBrowser6r)
Host: www.test.com
Connection: Keep-Alive
Cookie: PHPSESSID=c593a9922d9303f79037177d0f489d22

HTTP/1.1 200 OK
Date: Fri, 08 Jul 2005 13:09:55 GMT
Server: Apache/1.3.27 (Win32) PHP/4.3.0
X-Powered-By: PHP/4.3.0
Last-Modified: Tue, 21 Jun 2005 20:22:02 GMT
Cache-Control: private, max-age=3600, pre-check=3600
Pragma: cache
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Encoding: gzip
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=windows-1251
 

kruglov

Новичок
max-age=3600 - это чего? час? ну подождите часок...

-~{}~ 08.07.05 17:09:

Last-Modified: Tue, 21 Jun 2005 20:22:02 GMT - ээ? а говорили, изменения вносили... А почему дата древняя?
 

Spear

почемучка
max-age=3600 - феномен какойто.
в хедерах отправляю:
header("Cache-Control: no-cache, must-revalidate, private, no-store, s-maxage=0, max-age=0, post-check=0, pre-check=0");

почему ставится час - не нзаю.

Last-Modified: Tue, 21 Jun 2005 20:22:02 GMT - то же феномен. я же сделал изменения - должны бы и измениться..

-~{}~ 08.07.05 18:21:

вопросец - как вообще могут появляться хедеры, которые я не отправляю?
может где-то недочет в самом движке сайта? И не вызываются хедеры, и браузер (или что там) отправляет сам 3600 на макс-эйж?
 

kruglov

Новичок
Spear
Все может быть... Отлаживать надо. Напечатайте echo этот filemtime...

Начните с простейшего скрипта, который выдает только хедеры last-modified и cache-control, причем вручную забитые какие-нить, посмотрите, что ловит браузер... Потом, если работает, добавляйте прочую функциональность.
 

ksnk

прохожий
Автор оригинала: Spear
$t=filemtime(__FILE__);
а если у меня страницы вида
junp.php?nav=10? (новости, напоример). Работать будет?
Ну, типа в документации написано, что __FILE__ - имя скрипта, который исполняется :) У меня , вроде, работает :)

-~{}~ 08.07.05 19:18:

Кстати, я не особенно прав в случае, кодга работаем с FF. Нужно бы писать не
PHP:
         $can_generate = $can_generate || ($lastmod !=$headers["If-Modified-Since"]) ;
, а
PHP:
         $can_generate = $can_generate || (!(strpos($headers["If-Modified-Since"],$lastmod )===false)) ;
 

kruglov

Новичок
Да, кстати! Насчет "junp.php?nav=10" - если контент собирается из нескольких источников (скрипт читает какой-то другой файл или базу), то очевидно, что last-modified должен являться датой самого нового компонента (max())
 

ksnk

прохожий
Кстати, мой пример так и делает. Он используется для показа картинки (я там случайно в конце не убрал хидер image/jpeg)/ Ну и ему для корректности нужно знать только собсвенную дату (filemtime(__FILE__)) и дату картинки (filemtime($filename)) из которых и выводится max...

Для контента, формирующегося из большого количества странно связаных файлов можно использовать
PHP:
 global $lastmod ; $lastmod=max($lastmod,filemtime(__FILE__))
для каждого нового "значимого" инклуда, и примерно то-же для выедаемых из базы(файла) данных...
 

Spear

почемучка
нашел причину!
каким-то образом нижеследующий код портит вышеотправленные хедеры

#Game update
session_cache_limiter('private');
session_cache_expire(60);
session_start("g".$id);
if(empty($_SESSION["g".$id]))
{
$db->sql_query("INSERT INTO stats VALUES ('$id', now(), '$status')");
$_SESSION["g".$id] = 1;
}
#

код использую для сбора некой статистики.
ВПоросец - а можно не убирая код и не урезая его функциональности исправитьь ошибку?
тесті показали что портит все строка
session_cache_limiter('private');

Для чего нужен код:
проверяю, установлена ли у юзера сессия такая-то, и если её нет - апдейтим таблицу статистики. Сделал на сессиях так как нужно избежать сильной накрутки (путем зажатия Ф5)
 

SiMM

Новичок
> но всеравно браузер грузит страрую версию
Это ж надо было столько морочить людям голову... Выкинь все свои извраты с хидерами - тебе не нужно пользовательское кэширование. Вообще. Тебе нужно, чтобы механизм пользовательского кэширования не работал. А не наоборот. Обо всём, что тебе нужно, позаботиться механизм сессий.
PHP FAQ: Сессии. Дополнительная информация:

> session_cache_limiter('private');
Тоже в сад. Потому что читать FAQ надо ВНИМАТЕЛЬНО, а не тупо копировать код, который там встречается. Там чётко сказано, зачем это нужно - какое это имеет отношение к твоему случаю?

> session_start("g".$id);
Тоже извращение какое-то. [m]session_start[/m]
 
Сверху