200 OK + 資源內容 + 緩存標識(Last-Modified、ETag) + 緩存策略(Cache-Control、Expires)。If-Modified-Since(對應 Last-Modified)與 If-None-Match(對應 ETag)。304 Not Modified(無 Body),瀏覽器讀取本地緩存;若已變 → 返回 200 OK + 新內容 + 新標識。| 標頭 | 方向 | 作用 |
|---|---|---|
Last-Modified | Response | 資源最後修改時間(GMT) |
If-Modified-Since | Request | 詢問資源是否在該時間後修改 |
ETag | Response | 資源唯一指紋(如內容哈希、版本號) |
If-None-Match | Request | 攜帶上次收到的 ETag 進行比對 |
Cache-Control | Response | 指定緩存策略(max-age、public、no-cache 等) |
Expires | Response | 絕對過期時間(HTTP/1.0 兼容) |
Pragma: no-cache | Response | HTTP/1.0 強制不緩存 |
<?php
// 配置:客戶端緩存 1 小時
$cacheHours = 1;
$cacheSeconds = $cacheHours * 3600;
$etagValue = 'myapp_v1'; // 可根據內容哈希動態生成
// 發送緩存策略頭
header('Cache-Control: public, max-age=' . $cacheSeconds);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cacheSeconds) . ' GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Pragma: public');
header('ETag: ' . $etagValue);
// 1. 檢查 If-None-Match (ETag)
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$clientEtag = trim($_SERVER['HTTP_IF_NONE_MATCH']);
if ($clientEtag === $etagValue) {
header('ETag: ' . $etagValue, true, 304);
exit;
}
}
// 2. 檢查 If-Modified-Since
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$clientTime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
// 允許緩存時間內視為未修改
if (time() - $clientTime < $cacheSeconds) {
header('ETag: ' . $etagValue, true, 304);
exit;
}
}
// 3. 正常輸出內容...
echo "頁面動態內容...";
?>
靜態 ETag 適用於整頁緩存。對於內容頻繁變化的頁面,應根據實際內容生成:
$content = generatePageContent(); // 你的業務邏輯
$etagValue = '"' . md5($content) . '"'; // 加雙引號符合 RFC 7232
header('ETag: ' . $etagValue);
// 輸出前再次檢查
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etagValue) {
header('ETag: ' . $etagValue, true, 304);
exit;
}
echo $content;
-gzip 後綴),導致 PHP 生成的 ETag 不匹配。解決:由 Web 服務器統一處理壓縮與 ETag,或 PHP 僅輸出未壓縮內容並禁用服務器端壓縮。Last-Modified 精度僅至秒,高頻更新場景必須配合 ETag。Cache-Control: no-cache 並非「不緩存」,而是「每次使用緩存前必須向服務器驗證」。真正禁止緩存用 no-store。Cache-Control: private,防止代理服務器緩存洩露隱私。合理利用瀏覽器緩存可大幅降低服務器負載與頻寬。核心策略:強緩存控制頻率,協商緩存保證一致性。PHP 端只需正確發送標頭並處理 If-None-Match/If-Modified-Since 即可實現 304 響應。