1. 程式人生 > >php控制客戶端快取

php控制客戶端快取

1.關於HTTP訊息

詳見: http://www.runoob.com/http/http-messages.html
http訊息中請求頭是瀏覽器要告訴伺服器的資訊,而響應頭是伺服器要告訴客戶端的資訊。這些頭的定義是HTTP協議定義好的,客戶端和伺服器通過解析訊息頭中資訊來完成各自的工作。比如:請求頭中Accept-Language:zh-CN,zh;q=0.8 告訴伺服器客戶端能接收的語言。

2.響應頭Cache-Control控制快取

這裡寫圖片描述
Cache-Control 一個用於定義快取指令的通用頭標。

快取策略:
有用的 Cache-Control響應頭資訊包括:

max-age=[秒] — 執行快取被認為是最新的最長時間。類似於過期時間,這個引數是基於請求時間的相對時間間隔,而不是絕對過期時間,[秒]是一個數字,單位是秒:從請求時間開始到過期時間之間的秒數。
s-maxage=[秒] — 類似於max-age屬性,除了他應用於共享(如:代理伺服器)快取
public — 標記認證內容也可以被快取,一般來說: 經過HTTP認證才能訪問的內容,輸出是自動不可以快取的;
private在伺服器設定了private比如:Cache-Control:private, max-age=60的情況下,表示只有使用者的瀏覽器可以快取private響應,不允許任何中繼Web代理對其進行快取 – 例如,使用者瀏覽器可以快取包含使用者私人資訊的HTML網頁,但是CDN不能快取。
no-cache — 強制每次請求直接傳送給源伺服器,而不經過本地快取版本的校驗。這對於需要確認認證應用很有用(可以和public結合使用),或者嚴格要求使用最新資料的應用(不惜犧牲使用快取的所有好處);
no-store — 不做快取
must-revalidate — 告訴快取必須遵循所有你給予副本的新鮮度。使用快取的時候每次必須傳送請求到伺服器校驗,比如通過If-Modified-Since或If-None-Match
proxy-revalidate — 和 must-revalidate類似,除了他只對快取代理伺服器起作用,舉例:Cache-Control: max-age=3600, must-revalidate
<?php
header("Content-type:text/html;charset=utf-8");

//用Cache-Control告訴瀏覽器有效期 5秒
header("Cache-Control:max-age=5");//等同於Cache-Control:public, max-age=5
$curr_time = date('Y-m-d H:i:s');
echo '伺服器時間:'.$curr_time;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title
>
Cache</title> </head> <body> <br> Time:<?php echo $curr_time; ?> <br> <a href='cache_sample.php'>重新整理時間</a> </body> </html>

這裡寫圖片描述

3.響應頭Expires控制快取

<?php
header("Content-type:text/html;charset=utf-8");

//用Cache-Control告訴瀏覽器有效期 5秒
// header("Cache-Control:max-age=5");//等同於Cache-Control:public, max-age=5
//設定10秒的有效期,時間格式是GMT //時間是當前伺服器時間 + 10秒 $expires = gmdate('D, d M Y H:i:s', time() + 10) . ' GMT'; header("Expires:$expires"); $curr_time = date('Y-m-d H:i:s'); echo '伺服器時間:'.$curr_time; ?>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Cache</title> </head> <body> <br> Time:<?php echo $curr_time; ?> <br> <a href='cache_sample.php'>重新整理時間</a> </body> </html>

這裡寫圖片描述
expires的弊端是有效期是以伺服器時間來設定,如果客戶端的時間和服務端時間有一定的時間差,快取的控制就有問題了,所以還是建議使用Cache-Control好!

上面的程式碼如果同時設定了

header("Cache-Control:max-age=5");
$expires = gmdate('D, d M Y H:i:s', time() + 10) . ' GMT'; 
//這個設定將無效
header("Expires:$expires");

Cache-Control(支援) 和 expires 同時設定有效期,以 Cache-Control設定的有效期為準

4.通過HTTP 304: Not Modified 使用快取

(1)響應頭包含 Expires, max-age的話,“開啟新視窗”、“位址列輸入url回車”這些瀏覽器行為不會使瀏覽器在Expires, max-age設定的有效期時間內去訪問伺服器,而是在快取中去獲取內容,但是”重新整理’”或”F5” 例外。
(2)訪問伺服器,根據伺服器響應來獲取內容。這種情況發生在設定了Cache-Control:no-cache 是否使用快取必須要通過伺服器驗證,或者是設定了 Expires,max-age但瀏覽器行為是“重新整理”或“F5”時候。’Last-Modified’、’ETag’、’must-revalidate’ 等有些特殊,不直接受瀏覽器行為影響,它們必須訪問伺服器後,再由伺服器判斷是直接傳送新的資源,還是傳送一個304 Not Modfied讓瀏覽器使用快取中的資源。

注意: CTRL+ F5是強制重新整理。

這裡寫圖片描述
ETag全稱Entity Tag,用來標識一個資源。在具體的實現中,ETag可以是資源的hash值,也可以是一個內部維護的版本號。但不管怎樣,ETag應該能反映出資源內容的變化,這是Http快取可以正常工作的基礎。Last-Modified的原理其實和ETag差不多,Last-Modified通過時間來標識資源。通過這樣的方式可以不必每次都獲取全部的資源達到更新的目的,能極大的節省伺服器的開銷,更有利於搜素引擎的抓取。

<?php
header("Content-type:text/html;charset=utf-8");

header("Cache-Control:no-cache");
//響應頭Last-Modified
$lastmodified = filemtime('./cache.php');
$lastmodifiedGMT = gmdate('D, d M Y H:i:s',$lastmodified). ' GMT';
header("Last-Modified:$lastmodifiedGMT");

//響應頭ETag
$etag = md5_file('./cache.php');
header("ETag:$etag");




if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] == $lastmodifiedGMT ||
    @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
        header("HTTP/1.1 304 Not Modified");
        exit;
    }

//返回304後,下面的內容不會向瀏覽器返回,而瀏覽器會使用之前的快取   
$curr_time = date('Y-m-d H:i:s');
echo '伺服器時間:'.$curr_time;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cache</title>
</head>
<body>
<br>
    Time:<?php  echo $curr_time; ?>
<br>
    <a href='cache_sample.php'>重新整理時間</a>
</body>
</html>

這裡寫圖片描述