PHP中的輸出緩沖控制詳解
在 PHP 中,我們直接進行 echo 、 或者 print_r 的時候,輸出的內(nèi)容就會直接打印出來。但是,在某些情況下,我們并不想直接打印,這個時候就可以使用輸出緩沖控制來進行輸出打印的控制。當(dāng)然,這一套功能并不僅限出針對打印的內(nèi)容,我們還可以做其它一些操作,這個我們放到最后再說。
清除輸出
首先,我們先來看看不讓 echo 之類的內(nèi)容打印輸出。
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; ob_end_clean();
相信有不少小伙伴應(yīng)該見過 ob_start() 這個函數(shù),它的作用就是開始一段輸出緩沖控制。在 ob_start() 之后的代碼中的輸出語句都會進入輸出緩沖區(qū),這個時候,如果我們調(diào)用了 ob_end_clean() 、 ob_clean() 或者 ob_get_clean() ,則不會有任何輸出了。它們?nèi)齻€的作用都是清除輸出緩沖區(qū)的內(nèi)容。具體的區(qū)別大家可以參考文章最后給出的函數(shù)說明或者官方文檔。
獲得輸出緩沖區(qū)的內(nèi)容
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; $v = ob_get_contents(); ob_end_clean(); echo $v;
上面說過,使用了 ob_end_clean() 就會清除輸出緩沖區(qū)里面的內(nèi)容,但是在這段代碼中,我們使用 ob_get_contents() 函數(shù)直接將緩沖區(qū)的內(nèi)容賦值給了變量 \v 。這時候,v。這時候,v 中就有了前面兩段 echo 中的內(nèi)容,也就是說,這個一套操作我們就拿到了本身應(yīng)該輸出的內(nèi)容,并將它保存在了變量中。這樣做有什么用呢?我們可以獲得類似于 phpinfo() 、 var_dump() 這些直接輸出函數(shù)的內(nèi)容了,并且不會打印在客戶端屏幕上。比如:
ob_start(); php_info(); $v = ob_get_contents(); ob_end_clean(); echo $v;
在 $v 中的內(nèi)容就是 php_info() 的內(nèi)容了。這就是輸出緩沖控制的第二個能力。
刷新(輸出)緩沖區(qū)內(nèi)容
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; flush(); ob_flush();
類似的,我們在緩沖區(qū)中想要再次直接輸出內(nèi)容,使用 flush() 、ob_flush() 、 ob_end_flush() 及 ob_get_flush() 就可以了,其實就是相當(dāng)于讓 ob_start() 之后的 echo 這類輸出語句重新生效并正常輸出。
另外,我們還可以使用一個函數(shù)進行自動的刷新。
ob_implicit_flush(); ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL;
使用 ob_implicit_flush() 之后,我們就不需要手動地調(diào)用 ob_flush() 之類的函數(shù)來刷新緩沖區(qū)內(nèi)容了。
一些檢測函數(shù)
ob_start(); ob_start(); echo 123, PHP_EOL; echo ob_get_length(), PHP_EOL; // 3 echo ob_get_level(), PHP_EOL; // 2 print_r(ob_get_status(true)); // Array // ( // [0] => Array // ( // [name] => default output handler // [type] => 0 // [flags] => 112 // [level] => 0 // [chunk_size] => 0 // [buffer_size] => 16384 // [buffer_used] => 0 // ) // [1] => Array // ( // [name] => default output handler // [type] => 0 // [flags] => 112 // [level] => 1 // [chunk_size] => 0 // [buffer_size] => 16384 // [buffer_used] => 17 // ) // ) ob_get_flush();
ob_get_length() 會返回當(dāng)前緩沖區(qū)里面內(nèi)容的長度,這里我們只打印了一個 123 ,在緩沖區(qū)中保存了3個字符,所以輸出的正是 3 。ob_get_level() 返回的是當(dāng)前緩沖區(qū)的層級,請注意,我們在上面調(diào)用了兩次 ob_start() ,也就是有兩層的緩沖區(qū),這個緩沖區(qū)是可以嵌套的。ob_get_status() 函數(shù)是緩沖區(qū)的狀態(tài)信息,字段的說明可以查看官方文檔,這里不再贅述。
使用 ob_start() 的回調(diào)函數(shù)來進行輸出緩沖區(qū)的內(nèi)容替換
這是一個例子,但是可以推廣到其他很功能,比如我們可以用來進行全局的輸出過濾、可以做 CSS 或 JS 文件的壓縮優(yōu)化等等。
ob_start(function($text){ return (str_replace("apples", "oranges", $text)); }); echo "It's like comparing apples to oranges", PHP_EOL; ob_get_flush(); // It's like comparing oranges to oranges
最后的輸出結(jié)果就是將 apples 內(nèi)容替換成了 oranges 內(nèi)容。
添加 URL 重寫器
output_add_rewrite_var('var', 'value'); // some links echo '<a href="file.php" rel="external nofollow" >link</a> <a rel="external nofollow" rel="external nofollow" >link2</a>'; // <a href="file.php?var=value" rel="external nofollow" >link</a> // <a rel="external nofollow" rel="external nofollow" >link2</a> // a form echo '<form action="script.php" method="post"> <input type="text" name="var2" /> </form>'; // <form action="script.php" method="post"> // <input type="hidden" name="var" value="value" /> // <input type="text" name="var2" /> // </form>
上面的代碼看出什么端倪了嘛?沒錯,使用 output_add_rewrite_var() 函數(shù),我們可以在 PHP 輸出的時候為 HTML 的鏈接或者表單代碼增加一個參數(shù)。有沒有想到什么使用場景?POST 表單的 CSRF 攻擊的防范。
這個函數(shù)會根據(jù) php.ini 文件中的 url_rewriter.tags 配置項來進行添加,在默認(rèn)情況下這個配置項只支持 from 表單,同時,它還可以支持 a 標(biāo)簽的href 、 area標(biāo)簽的href 、 frame標(biāo)簽的src 、 input標(biāo)簽的src 等等。也就是說,會在這些標(biāo)簽相對應(yīng)的屬性中自動添加字段。當(dāng)然,它也有一個反函數(shù) output_reset_rewrite_vars() 用于取消之前增加的這個參數(shù)。
總結(jié)
關(guān)于輸出緩沖控制這塊還有很多好玩的東西,不過限于篇幅我們先介紹到這里,將來踫到什么好的功能的應(yīng)用我們再單獨講解?,F(xiàn)在基于 Swoole 的應(yīng)用越來越多,當(dāng)我們需要將 TP 、 Laravel 這類傳統(tǒng)框架轉(zhuǎn)換成支持 Swoole 的時候,往往就需要在入口文件使用輸出緩沖控制來進行修改。因為傳統(tǒng)框架基本都是直接進行 echo 之類的輸出的,而在 Swoole 中,echo 這類的內(nèi)容是直接打印在控制臺的,這就需要我們通過 ob_get_contents() 能力獲得全部的輸出再通過 response->end() 來進行實際的響應(yīng)。另外,還有一些其他的場景也會用到輸出緩沖控制:
1.在PHP中,像header(), session_start(), setcookie() 等這樣的發(fā)送頭文件的函數(shù)前,不能有任何的輸出,而利用輸出緩沖控制函數(shù)可以在這些函數(shù)前進行輸出而不報錯
2.對輸出的內(nèi)容進行處理,例如生成靜態(tài)緩存文件、進行g(shù)zip壓縮輸出,這算是較常用的功能了
3.捕獲一些不可獲取的函數(shù)輸出,例如phpinfo(), var_dump() 等等,這些函數(shù)都會將運算結(jié)果顯示在瀏覽器中,而如果我們想對這些結(jié)果進行處理,則用輸出緩沖控制函數(shù)是個不錯的方法。說的通俗點,就是這類函數(shù)都不會有返回值,而要獲取這些函數(shù)的輸出數(shù)據(jù),就要用到輸出緩沖控制函數(shù)
4.對一些數(shù)據(jù)進行實時的輸出
最后,再給出輸出緩沖控制相關(guān)的函數(shù)說明,具體內(nèi)容大家還是要多看官方文檔的介紹。
- flush — 刷新輸出緩沖
- ob_clean — 清空(擦掉)輸出緩沖區(qū)
- ob_end_clean — 清空(擦除)緩沖區(qū)并關(guān)閉輸出緩沖
- ob_end_flush — 沖刷出(送出)輸出緩沖區(qū)內(nèi)容并關(guān)閉緩沖
- ob_flush — 沖刷出(送出)輸出緩沖區(qū)中的內(nèi)容
- ob_get_clean — 得到當(dāng)前緩沖區(qū)的內(nèi)容并刪除當(dāng)前輸出緩。
- ob_get_contents — 返回輸出緩沖區(qū)的內(nèi)容
- ob_get_flush — 刷出(送出)緩沖區(qū)內(nèi)容,以字符串形式返回內(nèi)容,并關(guān)閉輸出緩沖區(qū)。
- ob_get_length — 返回輸出緩沖區(qū)內(nèi)容的長度
- ob_get_level — 返回輸出緩沖機制的嵌套級別
- ob_get_status — 得到所有輸出緩沖區(qū)的狀態(tài)
- ob_gzhandler — 在ob_start中使用的用來壓縮輸出緩沖區(qū)中內(nèi)容的回調(diào)函數(shù)。ob_start callback function to gzip output buffer
- ob_implicit_flush — 打開/關(guān)閉絕對刷送
- ob_list_handlers — 列出所有使用中的輸出處理程序。
- ob_start — 打開輸出控制緩沖
- output_add_rewrite_var — 添加URL重寫器的值(Add URL rewriter values)
- output_reset_rewrite_vars — 重設(shè)URL重寫器的值(Reset URL rewriter values)
測試代碼:
以上就是PHP中的輸出緩沖控制詳解的詳細內(nèi)容,更多關(guān)于PHP 輸出緩沖控制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
PHP實現(xiàn)的隨機IP函數(shù)【國內(nèi)IP段】
這篇文章主要介紹了PHP實現(xiàn)的隨機IP函數(shù),可實現(xiàn)輸出國內(nèi)IP段的功能,涉及php字符串與數(shù)組的計算操作相關(guān)技巧,需要的朋友可以參考下2016-07-07php中unlink()、mkdir()、rmdir()等方法的使用介紹
unlink()函數(shù)刪除文件 、mkdir()函數(shù)創(chuàng)建目錄、rmdir()函數(shù)刪除目錄這些方法在文件相關(guān)的處理方法會經(jīng)常使用到,本文整理了一些,需要的朋友可以了解下2012-12-12ThinkPHP6使用最新版本Endroid/QrCode生成二維碼的方法實例
這篇文章主要介紹了ThinkPHP6使用最新版本Endroid/QrCode生成二維碼的方法,結(jié)合實例形式詳細分析了ThinkPHP6使用最新版本Endroid/QrCode生成二維碼具體步驟、原理、實現(xiàn)方法與相關(guān)注意事項,需要的朋友可以參考下2023-07-07PHP獲取和操作配置文件php.ini的幾個函數(shù)介紹
當(dāng)你沒辦法修改php.ini配置文件怎么辦,沒事,php有一套設(shè)置和獲取配置信息的函數(shù)2013-06-06asp函數(shù)split()對應(yīng)php函數(shù)explode()
今天小編就為大家分享一篇關(guān)于asp函數(shù)split()對應(yīng)php函數(shù)explode(),小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02PHP使用DOM和simplexml讀取xml文檔的方法示例
這篇文章主要介紹了PHP使用DOM和simplexml讀取xml文檔的方法,結(jié)合實例形式分析了php使用DOM及simplxml針對xml文件的創(chuàng)建、載入、讀取等相關(guān)操作技巧,需要的朋友可以參考下2017-02-02php中cookie與session的區(qū)別點總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于php中cookie與session的區(qū)別點總結(jié)內(nèi)容,有興趣的朋友們可以參考學(xué)習(xí)下。2021-12-12