设为首页 收藏本站
查看: 468|回复: 0

[经验分享] PHP与浏览器缓存

[复制链接]

尚未签到

发表于 2017-3-28 10:29:27 | 显示全部楼层 |阅读模式
我们往往在服务器上对缓存设置进行各种优化方案,但是我们却很少注意到客户端缓存,准确的说是浏览器的缓存机制。

其实每种浏览器都有缓存策略,会暂时将每一个浏览过的文件缓存在一个特殊的文件夹里。我们就可以在用户重复提交页面请求的时候,告诉用户这个页 面没有改变,可以调用缓存。 那我们怎么知道用户有没有这个页面的缓存数据呢? 其实浏览器在发送请求的时候会先发送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 协议
<wbr><br>header("Cache-Control: no-cache, must-revalidate"); <wbr><br><wbr><wbr><br>//告诉客户端浏览器不使用缓存,兼容HTTP 1.0 协议 <wbr><br>header("Pragma: no-cache"); <wbr></wbr></wbr></wbr></wbr></wbr></wbr>


根据这个原理,可以用在不经常更新或者需要经常刷新的页面,可以大大减轻服务器的负担,因为它如果发现客户端有缓存,就向客户端发送一个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")
  • {
  • 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);
  • }

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); }
另外,当GZIP和ETAG同时使用时有时会出问题,就是ETAG没有值,这个问题是普遍存在的,我暂时没有找到相关的原因,网上搜了一会,普遍的人称之为BUG。

基于以上原因,关于PHPBLOG的客户端缓存是以下来处理的(同时对HTTP_IF_NONE_MATCH和HTTP_IF_MODIFIED_SINCE进行判断):
PHP 代码复制到剪贴板

  • if($_SERVER['HTTP_IF_NONE_MATCH'])
  • {
  • if($_SERVER['HTTP_IF_NONE_MATCH']=='phpblog')
  • {
  • header('Etag:phpblog',true,304);//控制浏览器缓存
  • $_SESSION['time_end']=microtime(true);
  • exit();
  • }
  • }
  • elseif($_SERVER['HTTP_IF_MODIFIED_SINCE'])//eg:Sun,02Nov200807:08:25GMT;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();
  • }
  • }

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(); } }
缓存的HEADER是这样来发送的:
PHP 代码复制到剪贴板

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

$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');//返回标识,用于标识上次的确访问过(浏览器中存在缓存)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-356293-1-1.html 上篇帖子: php 文件上传 简单代码 下篇帖子: php常用功能函数收集
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表