php中ob函數(shù)緩沖機(jī)制深入理解
下面就php中ob函數(shù)緩沖機(jī)制通過(guò)文字說(shuō)明加代碼分析的形式給大家展示如下:
對(duì)于一個(gè)剛剛?cè)腴T(mén)的php程序員來(lái)說(shuō),php緩沖區(qū)是幾乎透明的。在他們心目中,一個(gè)echo print_r 函數(shù),數(shù)據(jù)便會(huì)‘嗖'的一聲飛到瀏覽器上,顯示出來(lái)。我也一直如此單純地認(rèn)為。 其實(shí),在技術(shù)的世界里,向來(lái)都是由簡(jiǎn)單到復(fù)雜,也許那些技術(shù)開(kāi)發(fā)者開(kāi)始單純?nèi)缒阄?,但是面?duì)殘酷的現(xiàn)實(shí),不得不調(diào)整策略,以期提高機(jī)器運(yùn)行效率,最后想到了那些讓我們贊嘆的idea。
說(shuō)到緩沖,也就是buffer,這里必須要和緩存做一下比較,單純地比較定義是無(wú)意義的,莫不如看看它們做什么。緩存解決的是如何快速查找利用數(shù)據(jù),節(jié)省cpu消耗問(wèn)題,而緩沖解決的是高速cpu與低速I(mǎi)/O設(shè)備不匹配的問(wèn)題。
再說(shuō)下本文的另一個(gè)主角,ob函數(shù),ob是output_buffering的簡(jiǎn)寫(xiě)。既然ob函數(shù)是php擴(kuò)展函數(shù),那么ob函數(shù)主要操作的也就是php buffer了。
簡(jiǎn)單說(shuō)完本文兩個(gè)主角,我們還必須回歸開(kāi)頭的主題,echo print_r函數(shù)輸出的數(shù)據(jù)是怎么到達(dá)瀏覽器讓用戶看到的呢?實(shí)際上的歷程是這樣的:
echo、print_r=>php output_buffering=>webServer buffer=>browser buffer=>browser display
我們可以清楚地看到,從echo、print_r函數(shù)到發(fā)送信息給客戶端經(jīng)歷了兩個(gè)緩沖區(qū),在客戶端還經(jīng)歷了一個(gè)瀏覽器緩沖區(qū)。我們本文主要討論的是php output_buffering。
未使用ob函數(shù)時(shí)緩沖區(qū)的使用情況
我們的代碼很多時(shí)候是根本不使用ob函數(shù)的,那么它們使用緩沖區(qū)了嗎?這要看php設(shè)置情況。緩沖區(qū)是通過(guò)php.ini中的output_buffering變量控制的。其默認(rèn)值是off,可以設(shè)置為on來(lái)打開(kāi)buffer。打來(lái)buffer后,即便程序中沒(méi)有用ob函數(shù),實(shí)際上代碼也是使用了緩沖區(qū)的。另外,不管php.ini中output_buffering的設(shè)置,cli模式下的php始終默認(rèn)是關(guān)閉的。
為什么要是緩沖區(qū)呢?簡(jiǎn)單來(lái)說(shuō),高速的cpu早早處理完自己的數(shù)據(jù),想通過(guò)線路傳遞給用戶,但是線路太窄了,一下輸送不過(guò)去。如果引入緩沖區(qū),cpu可以將快速將生成的數(shù)據(jù)放入緩沖區(qū),然后自己哪兒涼快兒哪兒呆著這歇著去了。緩沖區(qū)根據(jù)指令適時(shí)將數(shù)據(jù)輸出。這個(gè)樣就合理解決了高速cpu與低速I(mǎi)/O設(shè)備的矛盾了。
緩沖區(qū)的數(shù)據(jù)什么時(shí)候輸出呢?1,當(dāng)緩沖區(qū)滿了的時(shí)候,緩沖是有容量大小的,到達(dá)極限則會(huì)自動(dòng)輸出內(nèi)容。2,腳本執(zhí)行完畢。很多小程序輸出內(nèi)容沒(méi)那么多,總不能等到緩沖區(qū)滿了再輸出吧~這一點(diǎn)再自然不過(guò)。
使用ob函數(shù)時(shí)緩沖區(qū)的使用情況
ob_start()
打開(kāi)輸出緩沖。這個(gè)函數(shù)是我們調(diào)用最多的一個(gè)函數(shù)之一。在output_buffering設(shè)置為on或者x k的情況下,這個(gè)函數(shù)與其說(shuō)是打開(kāi)輸出緩沖,還不如說(shuō)將輸出緩沖擴(kuò)充到很大。當(dāng)然在output_buffering設(shè)置為off的條件下,ob_start會(huì)起到打開(kāi)buffer的作用。ob_start()還可以傳遞一個(gè)可選參數(shù) output_callback 函數(shù),php官方手冊(cè)有詳細(xì)說(shuō)明。
ob_get_contents()
只是得到輸出緩沖區(qū)的內(nèi)容,但不清除它。
ob_end_clean()與ob_clean()
這兩個(gè)函數(shù)從字面意思上就可以看出其區(qū)別。前者清除緩沖區(qū)內(nèi)容并且關(guān)閉,后者僅僅是做清除工作。需要注意的是,使用了這兩個(gè)函數(shù),在前面使用了echo、print_r等函數(shù)不會(huì)輸出內(nèi)容。
筆者曾經(jīng)試圖通過(guò)print_r打印出ob_get_contents()的內(nèi)容,然后調(diào)用ob_clean()清除緩沖區(qū),以免影響后面對(duì)緩沖區(qū)的操作,屢屢失敗。仔細(xì)想想,print_r的內(nèi)容再次寫(xiě)入緩沖區(qū),而后面做了ob_clean()的操作,自然不會(huì)有任何輸出。在ob_clean操作之前調(diào)用ob_flush()函數(shù)便可達(dá)到預(yù)想的效果。
ob_flush()與flush()
ob_flush()送出緩沖區(qū)的內(nèi)容并且丟棄內(nèi)容。因而在此函數(shù)之前最好采用ob_get_contents()獲得緩沖區(qū)內(nèi)容。flush()刷出服務(wù)器端緩沖,并且發(fā)往客戶端。因而從流程上來(lái)說(shuō),應(yīng)該是先調(diào)用ob_flush()而后再調(diào)用flush函數(shù)。
另外說(shuō)明下再Apache buffer flush()的工作原理:在apache module的sapi下,flush會(huì)通過(guò)調(diào)用sapi_module()的flush成員函數(shù)指針,間接使用apache的api::ap_rflush刷新apache的輸出緩沖區(qū)。當(dāng)然apache其他模塊比如mod_gzip可能改變這個(gè)動(dòng)作的結(jié)果,可能自己進(jìn)行輸出緩沖區(qū),這將導(dǎo)致flush()函數(shù)產(chǎn)生的結(jié)果不會(huì)立即被送到客戶端瀏覽器。
ob_get_clean()
如果你已經(jīng)熟練掌握ob_get_contents()和ob_clean(),那這個(gè)函數(shù)就很簡(jiǎn)單了。因?yàn)樗乔皟烧叩慕Y(jié)合體。它主要是得到當(dāng)前緩沖區(qū)的內(nèi)容并刪除當(dāng)前輸出緩沖區(qū)。
ob函數(shù)還有很多,但大部分用法比較簡(jiǎn)單,理解較為容易。大家可以參照php手冊(cè) ,里面會(huì)有詳細(xì)的解釋。本文列出了筆者開(kāi)始并不是很理解的一些函數(shù),當(dāng)然今后還會(huì)有新的問(wèn)題出現(xiàn),想到問(wèn)題并且解決問(wèn)題,生活的樂(lè)趣也許就在此處吧。
以上內(nèi)容就是本文針對(duì)php中ob函數(shù)緩沖機(jī)制深入理解,希望對(duì)大家今后學(xué)習(xí)有所幫助。
相關(guān)文章
基于php偽靜態(tài)的實(shí)現(xiàn)詳細(xì)介紹
本篇文章介紹了,基于php偽靜態(tài)的實(shí)現(xiàn)詳細(xì)分析。需要的朋友參考下2013-04-04Yii框架在頁(yè)面輸出執(zhí)行sql語(yǔ)句以方便調(diào)試的實(shí)現(xiàn)方法
這篇文章主要介紹了Yii框架在頁(yè)面輸出執(zhí)行sql語(yǔ)句以方便調(diào)試的實(shí)現(xiàn)方法,涉及yiidebugtb的使用,是比較實(shí)用的技巧,需要的朋友可以參考下2014-12-12Codeigniter的一些優(yōu)秀特性總結(jié)
本文總結(jié)了一下Codeigniter的一些優(yōu)秀特性,算是個(gè)人的一些心得分享,推薦給大家。2015-01-01thinkPHP使用post方式查詢時(shí)分頁(yè)失效的解決方法
這篇文章主要介紹了thinkPHP使用post方式查詢時(shí)分頁(yè)失效的解決方法,通過(guò)使用JavaScript動(dòng)態(tài)修改頁(yè)面元素結(jié)合thinkPHP查詢語(yǔ)句解決分頁(yè)失效的問(wèn)題,需要的朋友可以參考下2015-12-12PHP分頁(yè)初探 一個(gè)最簡(jiǎn)單的PHP分頁(yè)代碼的簡(jiǎn)單實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇PHP分頁(yè)初探 一個(gè)最簡(jiǎn)單的PHP分頁(yè)代碼的簡(jiǎn)單實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06Yii2框架可逆加密簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了Yii2框架可逆加密簡(jiǎn)單實(shí)現(xiàn)方法,涉及Yii框架encryptByPassword()與decryptByPassword()函數(shù)簡(jiǎn)單使用方法,需要的朋友可以參考下2017-08-08安裝docker和docker-compose實(shí)例詳解
在本篇文章里小編給大家分享的是關(guān)于安裝docker和docker-compose的具體實(shí)例和代碼,需要的朋友們可以學(xué)習(xí)下。2019-07-07