php 实现协商缓存
协商缓存实现原理
协商缓存通过服务器与浏览器之间的HTTP头交互实现,主要依赖Last-Modified/If-Modified-Since和ETag/If-None-Match两组头部。当资源未变化时返回304状态码,减少数据传输。
基于Last-Modified的实现
$filePath = 'path/to/resource.txt';
$lastModified = filemtime($filePath);
$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : 0;
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");
if ($lastModified <= $ifModifiedSince) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Content-Type: text/plain");
readfile($filePath);
基于ETag的实现
$filePath = 'path/to/resource.txt';
$fileContent = file_get_contents($filePath);
$eTag = md5($fileContent);
$ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
trim($_SERVER['HTTP_IF_NONE_MATCH']) : '';
header("ETag: $eTag");
if ($ifNoneMatch === $eTag) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Content-Type: text/plain");
echo $fileContent;
组合使用两种策略
$filePath = 'path/to/resource.txt';
$lastModified = filemtime($filePath);
$fileContent = file_get_contents($filePath);
$eTag = md5($fileContent);
$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : 0;
$ifNoneMatch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
trim($_SERVER['HTTP_IF_NONE_MATCH']) : '';
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");
header("ETag: $eTag");
if (($lastModified <= $ifModifiedSince) || ($ifNoneMatch === $eTag)) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header("Content-Type: text/plain");
echo $fileContent;
注意事项
确保在发送304响应前没有输出任何内容 对于动态内容,需要手动计算ETag或Last-Modified值 ETag比Last-Modified更精确,能检测到秒级内的修改 某些CDN会对ETag进行特殊处理,需测试兼容性







