• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

深入PHP与浏览器缓存的分析_php实例

php 搞代码 4年前 (2022-01-25) 39次浏览 已收录 0个评论

我们往往在服务器上对缓存设置进行各种优化方案,但是我们却很少注意到客户端缓存,准确的说是浏览器的缓存机制。
其实每种浏览器都有缓存策略,会暂时将每一个浏览过的文件缓存在一个特殊的文件夹里。我们就可以在用户重复提交页面请求的时候,告诉用户这个页 面没有改变,可以调用缓存。 那我们怎么知道用户有没有这个页面的缓存数据呢? 其实浏览器在发送请求的时候会先发送http头,一般象这样:
Date: Sun, 30 Jul 2006 09:18:11 GMT
Content-Type: image/gif
Last-Modified: Wed, 19 Jul 2006 07:40:06 GMT
ETag: “8c55da8d6abc61:2327”
Content-Length: 14757
其中
Last-Modified: Wed, 19 Jul 2006 07:40:06 GMT
ETag: “8c55da8d6abc61:2327”
就是有关页面的缓存信息的。然后如果服务器返回的响应代码不是HTTP 200 (OK),而是 304的话,浏览器就会从缓存中读取数据。
//告诉客户端浏览器不使用缓存,HTTP 1.1 协议
header(“Cache-Control: no-cache, must-revalidate”);

//告诉客户端浏览器不使用缓存,兼容HTTP 1.0 协议
header(“Pragma: no-cache”);
根据这个原理,可以用在不经常更新或者需要经常刷新的页面,可以大大减轻服务器的负担,因为它如果发现客户端有缓存,就向客户端发送一个304响应,然后停止程序的执行。

浏览器发出的请求中包含If-Modified-Since和If-None-Match 两个参数,第一个表示询问数据的最后修改时间是否是Thu,19 Jun 2008 16:24:01 GMT 然后服务器就会检查数据的最后修改时间,如果是该时间则返回状态码304(表示没有修改),此时当浏览器收到状态码是304时就不会下载数据而是从本地缓 存中调用。然而只有本地缓存中存在着该请求资源的数据时浏览器才会发送If-Modified-Since参数并且其值为上一次服务器所返回的Last- Modified的值(并不是所有的服务器都支持If-Modified-Since和If-None-Match );If-None-Match的功能也类似,它是由服务器返回的Etag的值生成的,可以是任意值,因为其作用仅仅是使服务器检查数据的修改时间然后返 回而已,只要不为none(默认值)或不为空其它的都可以。

所以我们可以在代码的最前部分设置返回给浏览的Etag为某个值,然后在这个资源被第二次请求的时候就会附带着一个If-None-Match 参 数,通过核实其值确实为所发出的Etag值时就可以指定服务器返回为304然后强行退出程序就行了,If-Modified-Since也是一样的做法这 里就只给出etag方法的php版(Last-Modified版的太常见了如设置缓存超时等等):
PHP 代码复制到剪贴板

    if ($_SERVER["HTTP_IF_NONE_MATCH"] == "claymorephp.com")<BR>    {<BR>        header('Etag:'.'zhaiyun.com',true,304<div>……本2文来源gaodai.ma#com搞##代!^码@网3</div><code>搞代gaodaima码</code>);<BR>        exit();<BR>    }<BR>    else {<BR>        header('Etag:'."claymorephp.com");<BR>    }<BR>    你还可以稍微改一下:<BR>    $expires=date("Ymd"); //一天后缓存过期<BR>    if ($_SERVER["HTTP_IF_NONE_MATCH"] == $expires)<BR>    {<BR>        header('Etag:'.$expires,true,304);<BR>        exit();<BR>    }<BR>    else {<BR>        header('Etag:'.$expires);<BR>    }<BR>if ($_SERVER["HTTP_IF_NONE_MATCH"] == "claymorephp.com") { header('Etag:'.'zhaiyun.com',true,304); exit(); } else { header('Etag:'."claymorephp.com"); } 你还可以稍微改一下: $expires=date("Ymd"); //一天后缓存过期 if ($_SERVER["HTTP_IF_NONE_MATCH"] == $expires) { header('Etag:'.$expires,true,304); exit(); } else { header('Etag:'.$expires); } <BR>


另外,当GZIP和ETAG同时使用时有时会出问题,就是ETAG没有值,这个问题是普遍存在的,我暂时没有找到相关的原因,网上搜了一会,普遍的人称之为BUG。
基于以上原因,关于PHPBLOG的客户端缓存是以下来处理的(同时对HTTP_IF_NONE_MATCH和HTTP_IF_MODIFIED_SINCE进行判断):
PHP 代码复制到剪贴板

      if($_SERVER['HTTP_IF_NONE_MATCH'])<BR>        {<BR>            if($_SERVER['HTTP_IF_NONE_MATCH'] == 'phpblog')<BR>            {<BR>                header('Etag:phpblog',true,304);//控制浏览器缓存<BR>                $_SESSION['time_end']=microtime(true);<BR>                exit();<BR>            }<BR>        }<BR>        else if($_SERVER['HTTP_IF_MODIFIED_SINCE'])//eg:Sun, 02 Nov 2008 07:08:25 GMT; length=35849<BR>        {<BR>            $array=explode(' ',$_SERVER['HTTP_IF_MODIFIED_SINCE']);<BR>            $gmday=$array[1];<BR>            $month_array=array(<BR>            "Jan"=>"01",<BR>            "Feb"=>"02",<BR>            "Mar"=>"03",<BR>            "Apr"=>"04",<BR>            "May"=>"05",<BR>            "Jun"=>"06",<BR>            "Jul"=>"07",<BR>            "Aug"=>"08",<BR>            "Sep"=>"09",<BR>            "Oct"=>"10",<BR>            "Nov"=>"11",<BR>            "Dec"=>"12");<BR>            $gmmonth=$month_array[$array[2]];<BR>            $gmyear=$array[3];<BR>            $array=explode(':',$array[4]);<BR>            $gmtimestamp=gmmktime($array[0],$array[1],$array[2],$gmmonth,$gmday,$gmyear);<BR>            if(gmmktime()-$gmtimestamp<$config_client_cache_time*60*60)<BR>            {<BR>                header('Etag:phpblog',true,304);//控制浏览器缓存<BR>                $_SESSION['time_end']=microtime(true);<BR>                exit();<BR>            }<BR>        }<BR>if($_SERVER['HTTP_IF_NONE_MATCH']) { if($_SERVER['HTTP_IF_NONE_MATCH'] == 'phpblog') { header('Etag:phpblog',true,304);//控制浏览器缓存 $_SESSION['time_end']=microtime(true); exit(); } } else if($_SERVER['HTTP_IF_MODIFIED_SINCE'])//eg:Sun, 02 Nov 2008 07:08:25 GMT; length=35849 { $array=explode(' ',$_SERVER['HTTP_IF_MODIFIED_SINCE']); $gmday=$array[1]; $month_array=array( "Jan"=>"01", "Feb"=>"02", "Mar"=>"03", "Apr"=>"04", "May"=>"05", "Jun"=>"06", "Jul"=>"07", "Aug"=>"08", "Sep"=>"09", "Oct"=>"10", "Nov"=>"11", "Dec"=>"12"); $gmmonth=$month_array[$array[2]]; $gmyear=$array[3]; $array=explode(':',$array[4]); $gmtimestamp=gmmktime($array[0],$array[1],$array[2],$gmmonth,$gmday,$gmyear); if(gmmktime()-$gmtimestamp<$config_client_cache_time*60*60) { header('Etag:phpblog',true,304);//控制浏览器缓存 $_SESSION['time_end']=microtime(true); exit(); } } <BR>


缓存的HEADER是这样来发送的:
PHP 代码复制到剪贴板

     $client_cache_time=$config_client_cache_time*60*60;//单位 - 秒<BR>            header('Cache-Control: public, max-age='.$client_cache_time);<BR>            header('Expires: '.gmdate('D, d M Y H:i:s',time()+$client_cache_time).' GMT');//设置页面缓存时间<BR>            header('Last-Modified: '.gmdate('D, d M Y H:i:s',time()).' GMT');//返回最后修改时间<BR>            header('Pragma: public');<BR>            header('Etag:phpblog');//返回标识,用于标识上次的确访问过(浏览器中存在缓存)<BR>$client_cache_time=$config_client_cache_time*60*60;//单位 - 秒 header('Cache-Control: public, max-age='.$client_cache_time); header('Expires: '.gmdate('D, d M Y H:i:s',time()+$client_cache_time).' GMT');//设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s',time()).' GMT');//返回最后修改时间 header('Pragma: public'); header('Etag:phpblog');//返回标识,用于标识上次的确访问过(浏览器中存在缓存)<BR>

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:深入PHP与浏览器缓存的分析_php实例
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址