在PHP网站开发中,可以通过设置HTTP响应头来启用ETag和Last-Modified机制,从而避免重复加载资源。以下是具体的实现方法:
<?php// 假设这是一个静态资源的路径$filePath = 'path/to/your/resource.txt';// 检查文件是否存在if (!file_exists($filePath)) { header("HTTP/1.1 404 Not Found"); exit;}// 获取文件的最后修改时间$lastModified = filemtime($filePath);// 生成 ETag(基于文件大小和最后修改时间)$fileSize = filesize($filePath);$etag = md5($fileSize . '-' . $lastModified);// 设置 Last-Modified 和 ETag 响应头header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");header("ETag: $etag");// 检查客户端的 If-None-Match 和 If-Modified-Since 请求头if ( (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) === $etag) || (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified)) { // 如果资源未修改,返回 304 Not Modified header("HTTP/1.1 304 Not Modified"); exit;}// 返回资源内容header("Content-Type: " . mime_content_type($filePath));header("Content-Length: " . $fileSize);readfile($filePath);
filemtime($filePath):
获取文件的最后修改时间,用于设置Last-Modified头。
filesize($filePath):
获取文件大小,用于生成ETag。
ETag生成:
使用文件大小和最后修改时间生成一个唯一的ETag值(这里用md5哈希)。
Last-Modified头:
使用gmdate将最后修改时间格式化为HTTP日期格式。
If-None-Match和If-Modified-Since检查:
如果客户端发送了If-None-Match或If-Modified-Since头,并且与当前资源的ETag或Last-Modified匹配,则返回304 Not Modified,告诉浏览器使用缓存。
返回资源内容:
如果资源有更新,则返回完整的资源内容。
第一次请求:
服务器返回资源内容,并附带Last-Modified和ETag头。
浏览器缓存资源。
后续请求:
浏览器发送If-None-Match(值为ETag)和If-Modified-Since(值为Last-Modified)头。
如果资源未修改,服务器返回304 Not Modified,浏览器使用缓存。
如果资源已修改,服务器返回新的资源内容。
动态内容:
对于动态生成的内容(如数据库查询结果),需要手动生成ETag和Last-Modified值。
性能优化:
对于静态资源,建议使用Web服务器(如Nginx或Apache)的缓存机制,而不是PHP。
时间同步:
确保服务器时间准确,否则Last-Modified可能会出错。
ETag生成算法:
ETag的生成算法可以根据需求调整,确保唯一性和性能。
如果资源是静态文件,可以直接在Web服务器中启用ETag和Last-Modified,而不需要通过PHP处理。
<FilesMatch "\.(html|css|js|jpg|png)$"> FileETag MTime Size </FilesMatch>
location ~* \.(html|css|js|jpg|png)$ { etag on;}
通过以上方法,可以在PHP网站中有效启用ETag和Last-Modified机制,减少重复加载资源,提升网站性能。