淺談PHP中output_buffering
一、我們要說一下php中的緩存大概有哪些!
在PHP中,我們可以粗略的將緩存分為客戶端緩存(Browser緩存),服務(wù)器端緩存(Server緩存)。由于PHP是基于B/S架構(gòu)的,所以,我們可以理解為瀏覽器端的緩存,服務(wù)器端緩存。
在服務(wù)器端PHP自帶的緩存中,主要可以分為兩大類緩存!程序緩存和OB緩存!這也是我們學(xué)習(xí)服務(wù)器端緩存的主要內(nèi)容!
在PHP中緩存的輸出順序?yàn)椋?br /> 打開了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,只有輸出數(shù)據(jù)達(dá)到了這個(gè)長度或者腳本結(jié)束瀏覽器才會(huì)將數(shù)據(jù)輸出在頁面上。
二、服務(wù)器端的響應(yīng)流程
A、客戶端向服務(wù)器端發(fā)送請(qǐng)求響應(yīng)!
B、Apache服務(wù)器加載了PHP模塊,開啟相應(yīng)的進(jìn)程(或線程)運(yùn)行相應(yīng)的PHP腳本頁面!
C、在沒有開啟OB緩存的情況下,運(yùn)行的結(jié)果全部都會(huì)被放到程序緩存中,然后打包發(fā)送給瀏覽器!瀏覽器對(duì)頁面進(jìn)行渲染,生成我們最后看到的WEB頁面!
D、在開啟了OB緩存的情況下,運(yùn)行的結(jié)果會(huì)被分別放入到OB緩存和程序緩存中,當(dāng)程序運(yùn)行到最后一行的時(shí)候,就會(huì)將OB緩存中的數(shù)據(jù)刷回到程序緩存中,然后打包返回給瀏覽器!瀏覽器對(duì)頁面進(jìn)行渲染,生成我們看到的WEB頁面!
三、OB緩存的常見用法!
a、output_buffering=4096,輸出較少的數(shù)據(jù)(少于一個(gè)buffer)
for($i=0; $i<5; $i++){ echo $i.'<br>'; sleep(1); }
運(yùn)行結(jié)果:等所有腳本全部運(yùn)行完成后,才輸出,因?yàn)閿?shù)據(jù)未滿一個(gè)buffer的大小。
b、output_buffering=4096,輸出較少的數(shù)據(jù)(少于一個(gè)buffer),關(guān)閉output_buffering,修改php.ini的output_buffering=0
echo str_repeat(" ",1024);//這里重復(fù)輸出一個(gè)空白 for($i=0; $i<5; $i++){ echo $i."<br/>"; flush(); sleep(1); }
運(yùn)行結(jié)果:因?yàn)榻昧薕B,不需要等到腳本運(yùn)行完畢就可以輸出,數(shù)據(jù)沒有在OB停留,可以看到斷斷續(xù)續(xù)間歇性輸出。echo ->browser buffering -> browser display
c、output_buffering=4096,輸出較大數(shù)據(jù)(大于一個(gè)buffer),不使用ob_start()
for($i=0; $i<5; $i++){ echo file_get_contents('f.txt').$i.'<br/><br/><br/><br/>'; sleep(2); }
運(yùn)行結(jié)果:f.txt為一個(gè)大于4kb的文件,因?yàn)榇笥赽uffer默認(rèn)值,buffer空間不夠用,每當(dāng)滿一個(gè)buffer就會(huì)輸出,所以可以看到間歇性輸出。
d、output_buffering=4096,輸出較大數(shù)據(jù)(大于一個(gè)buffer),使用ob_start()
ob_start(); for($i=0; $i<5; $i++){ echo file_get_contents('f.txt').$i.'<br/><br/><br/><br/>'; sleep(2); }
運(yùn)行結(jié)果:因?yàn)槭褂昧薿b_start(),會(huì)為buffer設(shè)置足夠大的空間,因此會(huì)保存到腳本執(zhí)行完畢后才會(huì)輸出。
e、output_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();
運(yùn)行結(jié)果:abc-hello-aa-abc-hello-aa-
f、output_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();
運(yùn)行結(jié)果:abc-hello-aa-
輸出緩沖區(qū)是可堆疊的,這即意謂著,當(dāng)有一個(gè) ob_start() 是活躍的時(shí), 你可以調(diào)用另一個(gè) ob_start() 。 只要確保又正確調(diào)用了 ob_end_flush() 恰當(dāng)?shù)拇螖?shù)即可。 如果有多重輸出回調(diào)函數(shù)是活躍的,輸出內(nèi)容會(huì)一直按嵌套的順序依次通過它們而被過濾。
注意:PHP5.2中,OB默認(rèn)是關(guān)閉的,5.3之后默認(rèn)是開啟的;
常用方法:
1.ob_start
激活output_buffering機(jī)制,一旦激活,腳本不再直接輸出到瀏覽器,而是暫時(shí)寫入php buffering區(qū)域。直到腳本運(yùn)行完畢后,才發(fā)送。
2.ob_get_contents
獲取php buffering中的數(shù)據(jù),注意:要在ob_end_clean()前調(diào)用,否則只會(huì)得到空字符。
3.ob_end_flush 和 ob_end_clean
ob_end_flush 會(huì)輸出php buffering 中的數(shù)據(jù),但不會(huì)清空。
ob_end_clean 不會(huì)輸出,只會(huì)清空php buffering中的數(shù)據(jù)。
4.ob_flush 、flush、ob_implicit_flush
ob_flush 會(huì)刷新php buffering 中的數(shù)據(jù)到程序緩存
flush 則會(huì)刷新程序緩存到瀏覽器緩存中
ob_implicit_flush 將打開或關(guān)閉絕對(duì)(隱式)刷送。絕對(duì)(隱式)刷送將導(dǎo)致在每次輸出調(diào)用后有一次刷送操作,以便不再需要對(duì) flush() 的顯式調(diào)用
四、OB緩存的作用!
OB緩存在各個(gè)方面都有應(yīng)用,但是,本人知道的主要是在兩個(gè)方面!
a、當(dāng)網(wǎng)站準(zhǔn)備做網(wǎng)站靜態(tài)化的時(shí)候,選擇OB緩存是一個(gè)不錯(cuò)的選擇!
b、解決Warning: Cannot modify header information - headers already sent by的錯(cuò)誤!
究其發(fā)生錯(cuò)誤的原因:是因?yàn)轫憫?yīng)頭和相應(yīng)主體位置錯(cuò)位導(dǎo)致的!正常情況下,服務(wù)器返回給瀏覽器的相應(yīng)內(nèi)容,應(yīng)該是:響應(yīng)頭+響應(yīng)主體!
但是,如果我們開啟了OB緩存,那么相應(yīng)頭信息(一般也就是header()函數(shù)進(jìn)行設(shè)置的信息),會(huì)被放入到程序緩存中!
而其他的輸出內(nèi)容,如:echo print_r var_dump 等,都會(huì)先被放入OB緩存中!
等程序結(jié)束的時(shí)候,或者OB緩存關(guān)閉的實(shí)話,將OB緩存的內(nèi)容在放入程序緩存中!從而保證響應(yīng)頭信息,始終在響應(yīng)主體內(nèi)容之前!
以上所述就是本文的全部內(nèi)容了,希望大家能夠喜歡。
相關(guān)文章
php實(shí)現(xiàn)上傳圖片保存到數(shù)據(jù)庫的方法
這篇文章主要介紹了php實(shí)現(xiàn)上傳圖片保存到數(shù)據(jù)庫的方法,可通過將圖片保存在數(shù)據(jù)庫實(shí)現(xiàn)多臺(tái)服務(wù)器共享文件的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-02-02PHP文件操作實(shí)例總結(jié)【文件上傳、下載、分頁】
這篇文章主要介紹了PHP文件操作,結(jié)合實(shí)例形式總結(jié)分析了php針對(duì)文件的上傳、下載、分頁等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2018-12-12php實(shí)現(xiàn)的一個(gè)簡單json rpc框架實(shí)例
這篇文章主要介紹了php實(shí)現(xiàn)的一個(gè)簡單json rpc框架實(shí)例,本文給出了RPC服務(wù)端和客戶端代碼以及應(yīng)用實(shí)例,需要的朋友可以參考下2015-03-03PHPwind整合最土系統(tǒng)用戶同步登錄實(shí)現(xiàn)方法
我的任務(wù)就是讓PHPWind和最土登錄同步,領(lǐng)導(dǎo)也知道我的技術(shù)能力有限,不怎么高要求,所以讓我先實(shí)現(xiàn),再考慮其他。趕鴨子上架,開工了。2010-12-12PHP保存Base64圖片base64_decode的問題整理
在本篇文章里小編給大家整理的是關(guān)于PHP保存Base64圖片base64_decode的問題,需要的朋友們參考下。2019-11-11PHP中UNIX時(shí)間戳和日期間的轉(zhuǎn)換與計(jì)算實(shí)例
這篇文章主要介紹了PHP中UNIX時(shí)間戳和日期間的轉(zhuǎn)換與計(jì)算實(shí)例,本文講解了將日期和時(shí)間轉(zhuǎn)變成UNIX時(shí)間戳、日期的計(jì)算等內(nèi)容,需要的朋友可以參考下2014-11-11詳解WordPress中簡碼格式標(biāo)簽編寫的基本方法
這篇文章主要介紹了詳解WordPress中簡碼格式標(biāo)簽編寫的基本方法,文中講到了添加和移除簡碼等的一些PHP函數(shù)的用法,需要的朋友可以參考下2015-12-12詳解如何使用PHP實(shí)現(xiàn)動(dòng)態(tài)代理IP的功能
動(dòng)態(tài)代理IP是一種通過不斷切換不同的代理IP來隱藏真實(shí)IP地址的技術(shù),動(dòng)態(tài)代理IP可以有效地解決IP被封鎖或訪問限制的問題,本文將使用PHP語言實(shí)現(xiàn)動(dòng)態(tài)代理IP的功能,需要的朋友可以參考下2024-03-03利用swoole+redis實(shí)現(xiàn)股票和區(qū)塊鏈服務(wù)
這篇文章主要給大家介紹了關(guān)于利用swoole+redis實(shí)現(xiàn)股票和區(qū)塊鏈服務(wù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)下吧。2017-09-09