| Раздел: PHP, MySQL, веб-программирование | Автор: foxweb |
| E-mail: |
Www: http://foxweb.net.ru |
| Просмотров: 2194 | Дата: 13.02.2007 |
Для начала немного теории. Любой веб-программист, работая в протоколом HTTP, обязан знать, что поведение браузера, сервера, а также способы и правила обработки данных определяются HTTP-протоколом. Вот как выглядит простой запрос к сайту http://detiasfalta.ru :
Запрос от браузера к серверу:
GET / HTTP/1.1
Host: detiasfalta.ru
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-aliveОтвет сервера браузеру:
HTTP/1.x 200 OK
Date: Mon, 12 Feb 2007 20:06:36 GMT
Server: Apache/1.3.37 (Win32) PHP/4.4.4
X-Powered-By: PHP/4.4.4
Expires: Tue, 28 Sep 2004 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Last-Modified: Mon, 12 Feb 2007 20:06:36GMT
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html
<html> данные, данные, данные... </html>
Запрос и ответ (точнее их заголовки) в протоколе HTTP во многом схожи и интуитивно понятны, и это сильно облегчает взаимодействие различных платформ, программ и серверов по всему миру. В большинстве случаев ответ сервера генерируется автоматически. Например, при запросе обычного HTML-файла его содержимое считывается с диска, к нему "приклеиваются" HTTP-заголовок (вспомнили конверт с почтовым штампом?) и всё это отправляется браузеру. Но иногда необходимо генерировать собственные заголовки, тогда это можно сделать прямо из скрипта. Интерпретатор PHP тоже формирует заголовок автоматически перед началом отправки данных, но программист всегда может добавить и свои заголовки с помощью функции header(). Как это делается, будет рассказано ниже.
Самый простой способ защиты от кэширования браузером страниц вашего сайта — записать в HTML-коде в разделе <head></head> следующие мета-тэги:
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="Mon, 12 Feb 2007 20:06:36GMT" />
<meta http-equiv="Last-Modified" content="Mon, 12 Feb 2007 20:06:36GMT" />
Это эквиваленты соответвующих HTTP-заголовков. Именно поэтому свойство мета-тэга так и называется — http-equiv.
Таким образом мы получаем четырёхкратную гарантию защиты от кэширования!
Есть и второй способ. В нём используются те же самые заголовки, но передаются они как часть HTTP-ответа. Прописывая их в HTML, то есть не совсем "по правилам" у нас нет никакой гарантии, что какой-нибудь хитроумный браузер распознает их и интерпретирует согласно протоколу HTTP. Итак наша цель — передать HTTP-заголовки согласно протоколу. Тут уж как ни крути, любой браузер обязан его соблюдать.
Чтобы передать свои HTTP-заголовки из PHP скрипта, нужно в сааамом-самом начале исходного текста, пока не отправился ни один байт данных, выполнить следующие команды:
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
header("Expires: ".gmdate("D, d M Y H:i:s")."GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")."GMT");
Как мы видим, те же самые заголовки, но они включаются в HTTP-ответ сервера наравне с остальными. Единственное правило — заголовки всегда должны отправляться первыми. Как только начинается блок данных — заголовки не действуют. Эта "особенность" (даже не особенность, а то что само по себе и должно быть) часто сбивает с толку юных веб-программистов. При попытке послать заголовок командой header() в момент, когда уже начался блок данных, интерпретатор PHP выдаст ошибку: headers already sent.
<html>
<?php
/* такой код выдаст ошибку, поскольку уже началась отправка HTML-текста */
header('Location: http://www.example.com/');
?>
В своих проектах я обычно использую оба способа, но прямая передача заголовков надёжнее. Ну и напоследок: если вы хотите, чтобы файлы на вашем сайте наоборот сохранялись в кэше браузера (например, они оочень редко обновляются), необходимо убрать заголовки Cache-Control и Pragma, а в заголовках Expires и Last-Modified установить любую дату в будущем. Тогда браузер подумает, что документ достаточно "свежий" и не будет его обновлять. Запретом кэширования не стоит злоупотреблять, поскольку современные браузеры и сами прекрасно знают, что и когда кэшировать и это здорово экономит трафик и снижает нагрузку на сервер. Смысла в запрете кэширования сайта, обновляющегося раз в год, нет никакого, а вот для обновляющегося каждый день кэширование лучше отключить.