У меня есть сайт PHP 5.1.0 (на самом деле это 5.2.9, но он также должен работать на 5.1.0+).
Страницы генерируются динамически, но многие из них в основном статичны. По статике я имею в виду, что контент не изменяется, но «шаблон» вокруг контента может меняться со временем.
Я знаю, что они уже несколько систем кэширования и фреймворков PHP уже там, но на моем хосте нет установленных APC или Memcached, и я не использую никаких фреймворков для этого конкретного проекта.
Я хочу, чтобы страницы были кэшированы (я думаю, по умолчанию PHP «disallow» cache). До сих пор я использую:
session_cache_limiter('private'); //Aim at 'public' session_cache_expire(180); header("Content-type: $documentMimeType; charset=$documentCharset"); header('Vary: Accept'); header("Content-language: $currentLanguage");
Я читал много учебников, но я не могу найти что-то простое (я знаю, что кеш-то что-то сложное, но мне нужны только некоторые базовые вещи).
Что такое «должно» иметь заголовки для отправки, чтобы помочь кешировать?
Благодаря!
Возможно, вы захотите использовать private_no_expire
вместо private
, но установите длительный срок действия для контента, который, как вы знаете, не изменится, и убедитесь, что вы обрабатываете запросы if-modified-since
и if-none-match
похожие на сообщение Эмиля.
$tsstring = gmdate('D, d MYH:i:s ', $timestamp) . 'GMT'; $etag = $language . $timestamp; $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false; if ((($if_none_match && $if_none_match == $etag) || (!$if_none_match)) && ($if_modified_since && $if_modified_since == $tsstring)) { header('HTTP/1.1 304 Not Modified'); exit(); } else { header("Last-Modified: $tsstring"); header("ETag: \"{$etag}\""); }
Где $etag
может быть контрольной суммой на основе содержимого или идентификатора пользователя, языка и временной метки, например
$etag = md5($language . $timestamp);
У вас должен быть заголовок Expires. Технически есть и другие решения, но заголовок Expires действительно самый лучший из них, потому что он говорит браузеру не перепроверять страницу до истечения срока и времени и просто обслуживать содержимое из кеша. Он отлично работает!
Также полезно проверить заголовок If-Modified-Since в запросе из браузера. Этот заголовок отправляется, когда браузер «неуверен», если содержимое в его кеше по-прежнему является правильной версией. Если с этого момента ваша страница не изменяется, просто отправьте код HTTP 304 (Not Modified). Вот пример, который отправляет код 304 в течение десяти минут:
<?php if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { if(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < time() - 600) { header('HTTP/1.1 304 Not Modified'); exit; } } ?>
Вы можете поместить этот чек на раннем этапе в свой код, чтобы сохранить ресурсы сервера.
<?php header("Expires: Sat, 26 Jul 2020 05:00:00 GMT"); // Date in the future ?>
Установка даты истечения срока действия кэшированной страницы – один из полезных способов кэширования ее на стороне клиента.
Вот небольшой класс, который выполняет кэширование http для вас. Он имеет статическую функцию, называемую «Init», для которой требуется 2 параметра, отметка времени, в которую последняя страница (или любой другой файл, запрашиваемый браузером) была последней модификацией, и максимальный возраст в секундах, в течение которого эта страница может быть сохранена в кеш браузером.
class HttpCache { public static function Init($lastModifiedTimestamp, $maxAge) { if (self::IsModifiedSince($lastModifiedTimestamp)) { self::SetLastModifiedHeader($lastModifiedTimestamp, $maxAge); } else { self::SetNotModifiedHeader($maxAge); } } private static function IsModifiedSince($lastModifiedTimestamp) { $allHeaders = getallheaders(); if (array_key_exists("If-Modified-Since", $allHeaders)) { $gmtSinceDate = $allHeaders["If-Modified-Since"]; $sinceTimestamp = strtotime($gmtSinceDate); // Can the browser get it from the cache? if ($sinceTimestamp != false && $lastModifiedTimestamp <= $sinceTimestamp) { return false; } } return true; } private static function SetNotModifiedHeader($maxAge) { // Set headers header("HTTP/1.1 304 Not Modified", true); header("Cache-Control: public, max-age=$maxAge", true); die(); } private static function SetLastModifiedHeader($lastModifiedTimestamp, $maxAge) { // Fetching the last modified time of the XML file $date = gmdate("D, j MYH:i:s", $lastModifiedTimestamp)." GMT"; // Set headers header("HTTP/1.1 200 OK", true); header("Cache-Control: public, max-age=$maxAge", true); header("Last-Modified: $date", true); } }
Возьмите свой выбор – или используйте их все! 🙂
header («Истекает: Чт, 01-янв-70 00:00:01 GMT»); header ('Last-Modified:'. gmdate ('D, d MYH: i: s'). 'GMT'); header ('Cache-Control: no-store, no-cache, must-revalidate'); header ('Cache-Control: post-check = 0, pre-check = 0', false); header ('Pragma: no-cache');
Я делал кеширование json на сервере, исходящем из фейсбука, ничто не работало, пока я не добавил флеш и скрыл отчет об ошибках. Я знаю этот код демонов, но хотел скорейшего исправления как можно скорее.
error_reporting(0); $headers = apache_request_headers(); //print_r($headers); $timestamp = time(); $tsstring = gmdate('D, d MYH:i:s ', $timestamp) . 'GMT'; $etag = md5($timestamp); header("Last-Modified: $tsstring"); header("ETag: \"{$etag}\""); header('Expires: Thu, 01-Jan-70 00:00:01 GMT'); if(isset($headers['If-Modified-Since'])) { //echo 'set modified header'; if(intval(time()) - intval(strtotime($headers['IF-MODIFIED-SINCE'])) < 300) { header('HTTP/1.1 304 Not Modified'); exit(); } } flush(); //JSON OP HERE
РАБОТАЕТ, как шарм.