此代码片段检查页面自上次显示以来是否已修改。如果是,则发送“304 未修改”标头并退出,否则呈现内容。将此代码片段放在要应用此智能缓存机制的每个 PHP 文件的顶部。如果您(必须)通过 php 提供静态内容并希望将其缓存为普通 HTML 或 CSS,则此方法特别有用。
<?php
//get the last-modified-date of this very file
$lastModified=filemtime(__FILE__);
//get a unique hash of this file (etag)
$etagFile = md5_file(__FILE__);
//get the HTTP_IF_MODIFIED_SINCE header if set
$ifModifiedSince=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false);
//get the HTTP_IF_NONE_MATCH header if set (etag: unique file hash)
$etagHeader=(isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false);
//set last-modified header
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $lastModified)." GMT");
//set etag-header
header("Etag: $etagFile");
//make sure caching is turned on
header('Cache-Control: public');
//check if page has changed. If not, send 304 and exit
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$lastModified || $etagHeader == $etagFile)
{
header("HTTP/1.1 304 Not Modified");
exit;
}
//your normal code
echo "This page was last modified: ".date("d.m.Y H:i:s",time());
?>
你好,
如果我将其嵌入到每个可能更改的文件中包含的 header.php 中,此代码是否也能工作?
提前感谢!
要将此代码片段保留在单独的文件中,仅在其他文件的顶部包含它,您可能应该将所有
__FILE__
出现的情况更改为$_SERVER['SCRIPT_FILENAME']
。您能否提供一个简短的分步教程,说明需要替换哪些变量以及如何实现?
非常感谢!
带有 ETag 的行应为
header("ETag: \"$etagFile\"");
我已经将您的代码添加到我的页面的最顶部并测试了我的页面 http://web-sniffer.net
无论我让 web-sniffer.net 访问页面多少次,它们都返回状态:HTTP/1.1 200 OK,而我并没有更改服务器上的文件。
如果您的代码在我的页面中工作,我将在第一次访问时看到 200 OK,但后续访问应该显示 304(未修改),对吧?
当我将您代码中的 $ifModifiedSince= 变量从 false 更改为 true 时,我每次都得到 304(未修改),这似乎不正确,因为第一次访问应该返回 200 OK,对吧?
谢谢!
这不起作用。即使更新后,浏览器仍显示缓存的页面。获得更新信息的唯一方法是按 F5。
更改此行
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$lastModified || $etagHeader == $etagFile)
为以下内容
if (@strtotime($ifModifiedSince)==$lastModified || $etagHeader == $etagFile)
我认为发生的事情是上面的行中的检查将始终返回 true,因为您在刚刚设置标头后查询“Last-Modified”标头。
OP 确实在重新设置标头之前将旧的“Last-Modified”标头存储在变量中,只是忘记在代码中编写它。
所以任何人都可以使这个东西工作?这似乎很有趣。
谢谢
是否有任何人迄今为止使用过此代码……?
你好,
是的,我在生产服务器上使用过该代码进行一些 CDN 缓存,通过一个平衡的代理,效果很好。
您可以使用 Chrome 调试器或 Firebug 轻松测试它。
– 享受
使此代码工作,但仅在包含这些函数后才有效,这些函数阻止 PHP 自动添加 no-cache 标头。
session_cache_limiter(‘public’); //这停止了 php 的默认 no-cache
session_cache_expire(5); //可选的过期时间(分钟)
效果很好,谢谢
你好,
我将此代码放在 MVC 应用程序中,并且工作正常……
我将代码放在引导文件中……
当我使用 Chrome 调试器检查时,我注意到一些资源获取 200 OK 状态,几乎所有资源都获取 304 状态……
我的问题是如何设置哪些资源应该缓存,哪些资源不应该缓存?
此应用程序必须在每次有人访问页面时更新页面的点击次数……在第一次之后,它不再更新……
我需要以某种方式控制哪些资源应该缓存,并能够仅为 css、js、jquery、图像等资源设置缓存……
谢谢
大家好……我最近阅读了关于 md5_file 函数的信息.. 使用它是否有问题.. 因为当我将其应用于生产站点时,它会导致加载速度非常慢,因为 md5_file 正在获取文件名,并且我还使用了“k”的建议来更改
md5_file(__FILE__) //到// md5_file($_SERVER['SCRIPT_FILENAME') )
谢谢,效果非常好。
此“$ifModifiedSince”变量有什么用?
代码似乎没有使用它。
仅当站点的网页直接映射到相应的 PHP 文件时才使用此功能。
如果 PHP 文件可以生成不同的内容,例如数据库中的文章,则 ETag 应基于实际内容,而不是生成它的 PHP 文件。
此外,当 PHP 脚本更改但输出保持不变时,ETag 应保持不变。
我正在使用 processwire cms 框架来构建网站。
我将代码片段发布到 php 模板中,但它不起作用。X-Cache-Status 始终为 MISS
这是代码,除了 $lastModified,它将在内容更新时自动更新。
#etagFile 将 md5 内容主体
上次修改;
$etagFile = md5($page->body);
$ifModifiedSince=(isset($_SERVER[‘HTTP_IF_MODIFIED_SINCE’]) ? $_SERVER[‘HTTP_IF_MODIFIED_SINCE’] : false);
$etagHeader=(isset($_SERVER[‘HTTP_IF_NONE_MATCH’]) ? trim($_SERVER[‘HTTP_IF_NONE_MATCH’]) : false);
header(“Last-Modified: “.gmdate(“D, d M Y H:i:s”, $lastModified).” GMT”);
header(“Etag: $etagFile”);
header(‘Cache-Control: public’);
if (@strtotime($_SERVER[‘HTTP_IF_MODIFIED_SINCE’])==$lastModified || $etagHeader == $etagFile)
{
header(“HTTP/1.1 304 Not Modified”);
exit;
}
////// 我的 cms 代码
?>
$ifModifiedSince 未被使用,也许它原本打算在这里使用
if (@strtotime($_SERVER[‘HTTP_IF_MODIFIED_SINCE’])==$lastModified || $etagHeader == $etagFile) { }
无论如何,代码本身效果很好,即使 11 年后,也要感谢。