如何在 PHP 中使用 HTTP 缓存标头
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1971721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use HTTP cache headers with PHP
提问by AlexV
I have a PHP 5.1.0 website (actually it's 5.2.9 but it must also run on 5.1.0+).
我有一个 PHP 5.1.0 网站(实际上它是 5.2.9 但它也必须在 5.1.0+ 上运行)。
Pages are generated dynamically but many of them are mostly static. By static I mean the content don't change but the "template" around the content can change over time.
页面是动态生成的,但其中许多页面大多是静态的。静态我的意思是内容不会改变,但内容周围的“模板”会随着时间的推移而改变。
I know they are several cache systems and PHP frameworks already out there, but my host don't have APC or Memcached installed and I'm not using any framework for this particular project.
我知道他们已经有几个缓存系统和 PHP 框架,但是我的主机没有安装 APC 或 Memcached,我没有为这个特定项目使用任何框架。
I want the pages to be cached (I think by default PHP "disallow" cache). So far I'm using:
我希望页面被缓存(我认为默认情况下 PHP“禁止”缓存)。到目前为止,我正在使用:
session_cache_limiter('private'); //Aim at 'public'
session_cache_expire(180);
header("Content-type: $documentMimeType; charset=$documentCharset");
header('Vary: Accept');
header("Content-language: $currentLanguage");
I read many tutorials but I can't find something simple (I know cache is something complex, but I only need some basic stuff).
我阅读了很多教程,但找不到简单的东西(我知道缓存很复杂,但我只需要一些基本的东西)。
What are "must" have headers to send to help caching?
什么是“必须”有要发送以帮助缓存的标头?
采纳答案by Steve-o
You might want to use private_no_expireinstead of private, but set a long expiration for content you know is not going to change and make sure you process if-modified-sinceand if-none-matchrequests similar to Emil's post.
您可能想使用private_no_expire代替private,但为您知道不会更改的内容设置一个长到期时间,并确保您处理if-modified-since和if-none-match请求类似于 Emil 的帖子。
$tsstring = gmdate('D, d M Y H: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}\"");
}
Where $etagcould be a checksum based on the content or the user ID, language, and timestamp, e.g.
哪里$etag可以是基于内容或用户 ID、语言和时间戳的校验和,例如
$etag = md5($language . $timestamp);
回答by Emil Vikstr?m
You must have an Expires header. Technically, there are other solutions, but the Expires header is really the best one out there, because it tells the browser to not recheck the page before the expiration date and time and just serve the content from the cache. It works really great!
您必须有一个 Expires 标头。从技术上讲,还有其他解决方案,但 Expires 标头确实是最好的解决方案,因为它告诉浏览器在到期日期和时间之前不要重新检查页面,只提供缓存中的内容。它真的很棒!
It is also useful to check for a If-Modified-Since header in the request from the browser. This header is sent when the browser is "unsure" if the content in it's cache is still the right version. If your page is not modified since that time, just send back an HTTP 304 code (Not Modified). Here is an example that sends a 304 code for ten minutes:
检查来自浏览器的请求中的 If-Modified-Since 标头也很有用。当浏览器“不确定”缓存中的内容是否仍然是正确的版本时,将发送此标头。如果您的页面从那时起没有被修改,只需发回一个 HTTP 304 代码(未修改)。这是一个发送 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;
}
}
?>
You can put this check early on in your code to save server resources.
您可以在代码中尽早进行此检查以节省服务器资源。
回答by S Pangborn
<?php
header("Expires: Sat, 26 Jul 2020 05:00:00 GMT"); // Date in the future
?>
Setting an expiration date for the cached page is one useful way to cache it on the client side.
为缓存页面设置过期日期是一种在客户端缓存它的有用方法。
回答by Jasper
Here's a small class that does http caching for you. It has a static function called 'Init' that needs 2 parameters, a timestamp of the date that the page (or any other file requested by the browser) was last modified and the maximum age, in seconds, that this page can be held in cache by the browser.
这是一个为你做 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 M Y H: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);
}
}
回答by Mike Foster
Take your pick - or use them all! :-)
随意挑选 - 或全部使用它们!:-)
header('Expires: Thu, 01-Jan-70 00:00:01 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H: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');
回答by abksharma
I was doing JSON caching at the server coming from Facebook feed nothing was working until I put flush and hid error reporting. I know this is not ideal code, but wanted a quick fix.
我在来自 Facebook 提要的服务器上进行 JSON 缓存,直到我放入flush 和hid 错误报告后才开始工作。我知道这不是理想的代码,但想要快速修复。
error_reporting(0);
$headers = apache_request_headers();
//print_r($headers);
$timestamp = time();
$tsstring = gmdate('D, d M Y H: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
This worked very well.
这非常有效。
回答by Amit Ghosh Anto
This is the best solution for php cache Just use this in the top of the script
这是php缓存的最佳解决方案只需在脚本顶部使用它
$seconds_to_cache = 3600;
$ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$seconds_to_cache");

