一我们要说一下 php 中的缓存大概有哪些!
在 PHP 中, 我们可以粗略的将缓存分为客户端缓存 (Browser 缓存), 服务器端缓存(Server 缓存) 由于 PHP 是基于 B/S 架构的, 所以, 我们可以理解为浏览器端的缓存, 服务器端缓存
在服务器端 PHP 自带的缓存中, 主要可以分为两大类缓存! 程序缓存和 OB 缓存! 这也是我们学习服务器端缓存的主要内容!
在 PHP 中缓存的输出顺序为:
打开了 php 输出缓存: echo,print -> php output_buffering -> server buffering -> browser buffering -> browser display
未打开 php 输出缓存: echo,print -> server buffering -> browser buffering -> browser display
浏览器的输出缓存: IE 为 256Bytes, Chrome 与 FireFox 为 1000Bytes, 只有输出数据达到了这个长度或者脚本结束浏览器才会将数据输出在页面上
二服务器端的响应流程
A 客户端向服务器端发送请求响应!
BApache 服务器加载了 PHP 模块, 开启相应的进程 (或线程) 运行相应的 PHP 脚本页面!
C 在没有开启 OB 缓存的情况下, 运行的结果全部都会被放到程序缓存中, 然后打包发送给浏览器! 浏览器对页面进行渲染, 生成我们最后看到的 web 页面!
D 在开启了 OB 缓存的情况下, 运行的结果会被分别放入到 OB 缓存和程序缓存中, 当程序运行到最后一行的时候, 就会将 OB 缓存中的数据刷回到程序缓存中, 然后打包返回给浏览器! 浏览器对页面进行渲染, 生成我们看到的 WEB 页面!
三 OB 缓存的常见用法!
aoutput_buffering=4096, 输出较少的数据(少于一个 buffer)
- for($i=0; $i<5; $i++){
- echo $i.'
- ';
- sleep(1);
- }
运行结果: 等所有脚本全部运行完成后, 才输出, 因为数据未满一个 buffer 的大小
boutput_buffering=4096, 输出较少的数据(少于一个 buffer), 关闭 output_buffering, 修改 php.ini 的 output_buffering=0
- echo str_repeat(" ",1024);// 这里重复输出一个空白
- for($i=0; $i<5; $i++){
- echo $i."
- ";
- flush();
- sleep(1);
- }
运行结果: 因为禁用了 OB, 不需要等到脚本运行完毕就可以输出, 数据没有在 OB 停留, 可以看到断断续续间歇性输出 echo ->browser buffering -> browser display
coutput_buffering=4096, 输出较大数据(大于一个 buffer), 不使用 ob_start()
- for($i=0; $i<5; $i++){
- echo file_get_contents('f.txt').$i.'
- ';
- sleep(2);
- }
运行结果: f.txt 为一个大于 4kb 的文件, 因为大于 buffer 默认值, buffer 空间不够用, 每当满一个 buffer 就会输出, 所以可以看到间歇性输出
doutput_buffering=4096, 输出较大数据(大于一个 buffer), 使用 ob_start()
- ob_start();
- for($i=0; $i<5; $i++){
- echo file_get_contents('f.txt').$i.'
- ';
- sleep(2);
- }
运行结果: 因为使用了 ob_start(), 会为 buffer 设置足够大的空间, 因此会保存到脚本执行完毕后才会输出
eoutput_buffering=On, 使用 ob_start()
- ob_start();
- echo "abc-";
- header("content-type:text/html;charset=utf-8");
- echo "hello-";
- ob_end_flush();
- echo "aa-";
- echo ob_get_contents();
运行结果: abc-hello-aa-abc-hello-aa-
foutput_buffering=Off, 使用 ob_start()
- ob_start();
- echo "abc-";
- header("content-type:text/html;charset=utf-8");
- echo "hello-";
- ob_end_flush();
- echo "aa-";
- echo ob_get_contents();
运行结果: abc-hello-aa-
输出缓冲区是可堆叠的, 这即意谓着, 当有一个 ob_start() 是活跃的时, 你可以调用另一个 ob_start() 只要确保又正确调用了 ob_end_flush() 恰当的次数即可 如果有多重输出回调函数是活跃的, 输出内容会一直按嵌套的顺序依次通过它们而被过滤
注意: PHP5.2 中, OB 默认是关闭的, 5.3 之后默认是开启的;
常用方法:
1.ob_start
激活 output_buffering 机制, 一旦激活, 脚本不再直接输出到浏览器, 而是暂时写入 php buffering 区域直到脚本运行完毕后, 才发送
2.ob_get_contents
获取 php buffering 中的数据, 注意: 要在 ob_end_clean()前调用, 否则只会得到空字符
3.ob_end_flush 和 ob_end_clean
ob_end_flush 会输出 php buffering 中的数据, 但不会清空
ob_end_clean 不会输出, 只会清空 php buffering 中的数据
4.ob_flush flushob_implicit_flush
ob_flush 会刷新 php buffering 中的数据到程序缓存
flush 则会刷新程序缓存到浏览器缓存中
ob_implicit_flush 将打开或关闭绝对 (隐式) 刷送绝对 (隐式) 刷送将导致在每次输出调用后有一次刷送操作, 以便不再需要对 flush() 的显式调用
四 OB 缓存的作用!
OB 缓存在各个方面都有应用, 但是, 本人知道的主要是在两个方面!
a 当网站准备做网站静态化的时候, 选择 OB 缓存是一个不错的选择!
b 解决 Warning: Cannot modify header information - headers already sent by 的错误!
究其发生错误的原因: 是因为响应头和相应主体位置错位导致的! 正常情况下, 服务器返回给浏览器的相应内容, 应该是: 响应头 + 响应主体!
但是, 如果我们开启了 OB 缓存, 那么相应头信息 (一般也就是 header() 函数进行设置的信息), 会被放入到程序缓存中!
而其他的输出内容, 如: echo print_r var_dump 等, 都会先被放入 OB 缓存中!
等程序结束的时候, 或者 OB 缓存关闭的实话, 将 OB 缓存的内容在放入程序缓存中! 从而保证响应头信息, 始终在响应主体内容之前!
来源: https://www.php1.cn/detail/php-97d3246cb2.html