За что я люблю PHP, так это за то, что гениальные вещи на нем пишутся в несколько строчек. В этой заметке я продолжу рассуждать о правильном использовании заголовков в PHP. Если вам не всё равно, как индексируется поисковиками ваш сайт, если вы хотите сэкономить трафик, вы нашли именно то, что нужно.
Как известно, кеширование на стороне браузера сокращает нагрузку на сервер. Но для часто обновляемых страниц у него есть существенный недостаток: информация в кеше может устареть и не соответствовать действительной информации.
Для каждого документа, отдаваемого сервером, желательно выдавать заголовок Last-Modified (в том числе для правильной индексации, например, Яндексом):
<?php
$mt = filemtime($file_name);
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $mt).' GMT');
?> Для часто обновляемых страниц (я не говорю «динамических», так как страница может каждый раз собираться интерпретатором PHP, но фактически изменяться крайне редко) можно запретить кеширование следующим набором заголовков:
<?php
function no_cache() {
header('Expires: Mon, 26 Jul 1997 00:00:00 GMT' );
header('Cache-Control: no-cache, must-revalidat e');
header('Pragma: no-cache');
}
?> В принципе, для удовлетворительной работы сайта этого достаточно. Однако вместо полного запрета кеширования лучше применить более гибкий механизм с использованием заголовка If-Modified-Since. Он присутствует в запросе браузера, если в его кеше есть копия документа, и его значение — некая дата изменения этой копии. PHP-скрипт может посмотреть на эту дату и решить, стоит ли отдавать браузеру свежую страницу, или сообщить, что страница не изменилась, отправив ответ 304 Not Modified. Вместе с отправкой заголовка Last-Modified, код примет вид:
<?php
function date2unixstamp($s) {
$months = array (
'Jan' => 1, 'Feb' => 2, 'Mar' =>3,
'Apr' => 4, 'May' => 5, 'Jun' =>6,
'Jul' => 7, 'Aug' => 8, 'Sep' =>9,
'Oct' => 10, 'Nov' => 11, 'Dec' =>12
);
$a = explode(' ', $s);
$b = explode(':', $a[4]);
return gmmktime($b[0], $b[1], $b[2], $months[$a[2]], $a[1], $a[3]);
}
$mt = filemtime($file_name);
$mt_str = gmdate('D, d M Y H:i:s', $mt).' GMT';
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$cache_mt = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
if (date2unixstamp($cache_mt) >= $mt) {
header('HTTP/1.1 304 Not Modified');
exit;
}
}
header('Last-Modified: '.$mt_str);
echo $text;
?>
В операторе if мы не использовали проверку на равенство $_SERVER["HTTP_IF_MODIFIED_SINCE"] == $mt_str, а преобразовали дату вида Sun, 28 Jan 2007 07:56:48 GMT в формат unixstamp и сравнивали с датой изменения оригинального документа. Это нужно для решения двух проблем.
Дело в том, что последние версии Opera и Firefox исправно копируют содержимое заголовка Last-Modified ответа сервера в заголовок запроса If-Modified-Since (именно поэтому нам нужно было установить Last-Modified), и проверкой на равенство вполне можно было бы обойтись. Но, как всегда, не обошлось без капризов IE 6. Он к заголовку If-Modified-Sinceдобавляет параметр length, в чем и заключается первая проблема. Ее можно решить применением функции strpos, если бы не вторая проблема — хитрости поисковых роботов. Все они (кроме робота Рамблера, который действует по описанной выше схеме) в заголовке If-Modified-Since (если вообще его используют) передают не значение из Last-Modified, а дату последнего скачивания документа. В такой ситуации уже нельзя обойтись без упомянутого перевода дат в unixstamp (что и делает функция date2unixstamp).
Как же работает кеширование в браузерах? Если оно не запрещено вызовом функции no_cache, то в Firefox и в IE страница сохраняется в кеше, при последующих запросах выдается только она. Чтобы обновить страницу в кеше, нужно нажать комбинацию клавиш
Если запретить кеширование страницы функцией no_cache, то Опера и Firefox при обращении к такой странице используют механизм с заголовком If-Modified-Since, и это правильно. То есть кеширование всё равно происходит, но браузер спрашивает у сервера, изменилась ли страница на самом деле, или нет. Однако IE запрет на кеширование воспринимает буквально. В ходе экспериментов стало ясно, что если из трех заголовков no_cache убрать второй, то IE версий 6 и 7 начинает работать так, как нам нужно. Может оказаться полезным корректное использование заголовка Expires. В нем можно установить время, в течение которого будет использоваться только локальная копия документа в кеше. Этот способ позволяет справиться с излишне навязчивым кешированием в IE. Например, чтобы копия в кеше была действительна в течение суток, нужно использовать такой оператор:
<?php
header('Expires: '.gmdate('D, d M Y H:i:s', time() + 86400).' GMT');
?> Итак, как же использовать все эти возможности протокола HTTP? Обработка заголовка If-Modified-Since полезна в любом случае. Например, Яндекс рекомендует ее использовать. Если вы экономите трафик и если страницы обновляются редко, то запрещать их кеширование не нужно. Можно запретить их кеширование, тогда вместо него произойдет запрос к серверу с If-Modified-Since и 304 ответом. Это немного увеличит трафик, но позволит получать более правильную статистику посещений: пользователь зашел на страницу, а мы ему говорим, что страница не изменилась, но в статистике его учитываем. Если документы обновляются часто, практически всегда стоит запрещать их кеширование. Выдача 304 ответа в большинстве случаев скомпенсирует возможное повышение трафика.
Помимо описанного метода для проверки актуальности копии документа в кеше существует еще один, основанный не на дате изменения страницы, а на уникальном хеш-коде содержимого страницы. Общее название для обоих методов — Conditional Get, вы можете ознакомиться с дополнительной информацией о них.
energetic
<?PHP
//Скрипт генерации временных ссылок, без БД или фременных файлов.
//Зачем использовать таблицы и SQL, если можно генерить ссылки с ключем, зависимым от времени?
//например так:
$timeout = 3600; // Один час
$filesdir = "downloads/"; // Слешь в конце
//
$secret = md5((int)(time() / $timeout)); //Всегда целое число, меняется раз в $timeout секунд;
if( isset($_GET['key']) ) {
if( ($_GET['key'] == $secret) && //проверка ключа
strlen($_GET['fn']) && file_exists($filesdir.$_GET['fn']) ) { //проверка файла
readfile($filesdir.$_GET['fn']);die; //читаем файл
} else {
header ( 'HTTP/1.1 404 Not Found' );//Файл не найден
die;
}
}
?>
Скачать:<a href="?fn=file.doc&key=<?PHP echo $secret;?>">file.doc</a>
Интересует ваше мнение, м.б. чтото упустил.Обновил сайт - файловый архив http://britter.ru.
Новый парсер .doc фалов, позволяет просматривать картинки в .doc файлах!
По формату файлов .docx – обновил парсер таблиц. Теперь они выглядят как таблицы :)
Установил форум, для обсуждения документов, вот думал что лучше форум или блог.
Для обсуждения всетаки лучше форум…
good
creative
Очень приятная новость! В интернете появилась новая биржа для продажи ссылок монетизации блога! Авторы этой биржи, уже имеют успешные проекты в сети :) Сейчас, пока невелико количество вебмастеров, вы можете зарегистрироваться там одним из первых. Я уже успел это сделать, что и вам советаю. Все таки лишние деньги не бывают лишние, а от вас ничего не требуется, кроме регистрации.
Все что нужно для участия в новой системе – это блог, с постом, размещенным более месяца назад. Все. Никаких кодов, и счечиков вас разместить на страницах своего блога, не просят, что очень упрощает процесс регистрации :)
В системе есть партнерская реферальная программа, которая позволяет получать до 25% с ваших реферов, в различные ситуациях. Для участия в партнерской программе, спешите зарегестрироваться по этой ссылке.
Выплаты поддерживаются на WebMoney. (R и Z кошельки), и другие платёжные системы, два раза в месяц. Очень приятная минималка для вывода – всего 100 руб.
После проверки вашего блога модератором, вы можете начинать зарабатывать!
Вы читаете журнал
zemin_serchugg