PHP函數(shù)參考03-輸出緩沖控制ob函數(shù)



原文:
PHP函數(shù)參考03-輸出緩沖控制ob函數(shù) - 9ong
PHP函數(shù)參考04-PHP選項與信息函數(shù)認識 - 9ong

php輸出緩沖

輸出緩沖相當于一個輸出內(nèi)容隊列,用于對接存儲速度、優(yōu)先級不同步的設(shè)備,讓這些設(shè)備的輸入輸出不阻塞,更加流暢。

默認情況下,php buffer是開啟的,而且該buffer默認值是4096byte。可以通過php.ini配置文件中找到output_buffering配置。

當echo、print等輸出用戶數(shù)據(jù)的時候,輸出數(shù)據(jù)都會寫入到php output_buffering中,直到output_buffering寫滿,會將這些數(shù)據(jù)通過tcp傳送給瀏覽器顯示。

也可以通過 ob_start()手動激活php output_buffering機制,使得即便輸出超過了4096byte數(shù)據(jù),也不真的把數(shù)據(jù)交給tcp傳給瀏覽器,因為ob_start()將php buffer空間設(shè)置到了足夠大 。只有直到腳本結(jié)束,或者調(diào)用ob_end_flush函數(shù),才會把數(shù)據(jù)發(fā)送給客戶端瀏覽器。

注意:在CLI模式下是關(guān)閉的,因為可能造成性能問題。

常用ob函數(shù)

  • ob_start

    此函數(shù)將打開輸出緩沖。當輸出緩沖激活后,腳本將不會輸出內(nèi)容(除http標頭外),相反需要輸出的內(nèi)容被存儲在內(nèi)部緩沖區(qū)中。

    ob_start接受一個callalbe的output_callback函數(shù)名。

    function callback($buffer){    
        return (str_replace("apples", "bananas", $buffer));
    }
    
    ob_start('callback');
    
    echo "It's like comparing apples to oranges.\n<br />";
    
    $contents = ob_get_contents();
    
    print_r("最終輸出內(nèi)容:".$contents);
    
    ob_end_flush();
    
  • ob_end_flush

    沖刷出(送出)輸出緩沖區(qū)內(nèi)容并關(guān)閉緩沖。

    區(qū)別于ob_flush,多了關(guān)閉緩沖區(qū)。

  • ob_end_clean

    清空(擦除)緩沖區(qū)并關(guān)閉輸出緩沖。

    區(qū)別于ob_clean,多了關(guān)閉緩沖區(qū)。

  • ob_get_contents

    返回輸出緩沖區(qū)的內(nèi)容。

  • flush與ob_flush

    在沒有開啟output_buffering時,腳本輸出的內(nèi)容都在服務(wù)器端處于等待輸出的狀態(tài) ,等待腳本結(jié)束或調(diào)用flush()將等待輸出的內(nèi)容立即發(fā)送到客戶端。

    開啟緩存后,腳本輸出的內(nèi)容存入了輸出緩沖中,這時沒有處于等待輸出狀態(tài)的內(nèi)容,直接使用flush()不會向客戶端發(fā)出任何內(nèi)容。

    而ob_flush()的作用就是將本來存在輸出緩沖中的內(nèi)容取出來(也就是官方文檔寫的:沖刷出(送出)輸出緩沖區(qū)中的內(nèi)容),設(shè)置為等待輸出狀態(tài),但不會直接發(fā)送到客戶端 ,這時你就需要先使用 ob_flush()再使用flush(),客戶端才能立即獲得腳本的輸出。

    所以在默認開啟output_buffering下,先ob_flush將沖刷出輸出緩沖區(qū)中的內(nèi)容,輸出內(nèi)容進入等待輸出狀態(tài),再flush將輸出內(nèi)容刷新給tcp推送給客戶端。

  • ob_implicit_flush()

    將打開或關(guān)閉絕對(隱式)刷送。絕對(隱式)刷送將導(dǎo)致在每次輸出調(diào)用后有一次刷送操作,以便不再需要對 flush() 的顯式調(diào)用。

    通俗點說就是不用再顯示的調(diào)用flush來輸出。

  • 更多ob函數(shù)

    只要我們理解了輸出緩沖機制,充分理解ob_start、ob_flush、ob_end_flush、flush、ob_get_contents函數(shù),其他比如ob_get_clean、ob_get_flush從字面也大概知道是什么含義了。

使用場景與小結(jié)

ob函數(shù)用于web場景,比如:

  • 腳本未結(jié)束前(可能腳本執(zhí)行時間較長),先輸出部分內(nèi)容
  • 腳本輸出前通過ob_start回調(diào)調(diào)整或檢查等處理輸出內(nèi)容
  • 腳本輸出前,記錄最后輸出內(nèi)容

對于沒有深入理解php輸出機制的小伙伴,不建議隨便使用php的ob函數(shù),一方面怕誤用,另一方面由于apache、nginx等web服務(wù)對于php輸出有或沒有或不同程度的緩沖,導(dǎo)致ob函數(shù)可能會有不一樣的效果,也就是官方在flush函數(shù)里介紹的,在個別web服務(wù)器里怎么樣,有些apache模塊怎么樣,一些瀏覽器怎么樣,也就是說效果很難一致的統(tǒng)一,所以我們不建議使用輸出緩沖控制ob函數(shù),除非不得已。

比如nginx有開啟proxy_buffering,php即使刷出緩沖區(qū)內(nèi)容,也會再被緩存在nginx層,另外還由于gzip壓縮,未滿輸出內(nèi)容區(qū)上限,也不會提前輸出到客戶端。

所以如果在nginx環(huán)境下想使用ob_flush\flush在腳本未結(jié)束前輸出部分內(nèi)容,就需要調(diào)整nginx配置:

proxy_buffering off;
gzip off;
fastcgi_keep_conn on;

當然ob_start(callable)、ob_end_flush()在服務(wù)端的效果還是一致,不論web服務(wù)器是哪個,還是能做到將輸出先寫入PHP的output buffer中,再傳遞給callable回調(diào)函數(shù),最后通過ob_flush\flush\ob_end_flush沖出。

參考

PHP: Output Control 函數(shù) - Manual

【解決方法】nginx中php ob_flush和flush不起作用 - longzhankunlun - 博客園


原文:
PHP函數(shù)參考03-輸出緩沖控制ob函數(shù) - 9ong
PHP函數(shù)參考04-PHP選項與信息函數(shù)認識 - 9ong

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

推薦閱讀更多精彩內(nèi)容