在 PHP 中,咱們直接進行 echo 、 或者 print_r 的時候,輸出的內容就會直接打印出來。可是,在某些狀況下,咱們並不想直接打印,這個時候就可使用輸出緩衝控制來進行輸出打印的控制。固然,這一套功能並不只限出針對打印的內容,咱們還能夠作其它一些操做,這個咱們放到最後再說。php
首先,咱們先來看看不讓 echo 之類的內容打印輸出。git
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; ob_end_clean();
相信有很多小夥伴應該見過 ob_start() 這個函數,它的做用就是開始一段輸出緩衝控制。在 ob_start() 以後的代碼中的輸出語句都會進入輸出緩衝區,這個時候,若是咱們調用了 ob_end_clean() 、 ob_clean() 或者 ob_get_clean() ,則不會有任何輸出了。它們三個的做用都是清除輸出緩衝區的內容。具體的區別你們能夠參考文章最後給出的函數說明或者官方文檔。github
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; $v = ob_get_contents(); ob_end_clean(); echo $v;
上面說過,使用了 ob_end_clean() 就會清除輸出緩衝區裏面的內容,可是在這段代碼中,咱們使用 ob_get_contents() 函數直接將緩衝區的內容賦值給了變量 \$v 。這時候,$v 中就有了前面兩段 echo 中的內容,也就是說,這個一套操做咱們就拿到了自己應該輸出的內容,並將它保存在了變量中。這樣作有什麼用呢?咱們能夠得到相似於 phpinfo() 、 var_dump() 這些直接輸出函數的內容了,而且不會打印在客戶端屏幕上。好比:瀏覽器
ob_start(); php_info(); $v = ob_get_contents(); ob_end_clean(); echo $v;
在 $v 中的內容就是 php_info() 的內容了。這就是輸出緩衝控制的第二個能力。緩存
ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL; flush(); ob_flush();
相似的,咱們在緩衝區中想要再次直接輸出內容,使用 flush() 、ob_flush() 、 ob_end_flush() 及 ob_get_flush() 就能夠了,其實就是至關於讓 ob_start() 以後的 echo 這類輸出語句從新生效並正常輸出。cookie
另外,咱們還可使用一個函數進行自動的刷新。session
ob_implicit_flush(); ob_start(); echo 111, PHP_EOL; echo "aaaa", PHP_EOL;
使用 ob_implicit_flush() 以後,咱們就不須要手動地調用 ob_flush() 之類的函數來刷新緩衝區內容了。app
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() 會返回當前緩衝區裏面內容的長度,這裏咱們只打印了一個 123 ,在緩衝區中保存了3個字符,因此輸出的正是 3 。ob_get_level() 返回的是當前緩衝區的層級,請注意,咱們在上面調用了兩次 ob_start() ,也就是有兩層的緩衝區,這個緩衝區是能夠嵌套的。ob_get_status() 函數是緩衝區的狀態信息,字段的說明能夠查看官方文檔,這裏再也不贅述。框架
這是一個例子,可是能夠推廣到其餘很功能,好比咱們能夠用來進行全局的輸出過濾、能夠作 CSS 或 JS 文件的壓縮優化等等。函數
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
最後的輸出結果就是將 apples 內容替換成了 oranges 內容。
output_add_rewrite_var('var', 'value'); // some links echo '<a href="file.php">link</a> <a href="http://example.com">link2</a>'; // <a href="file.php?var=value">link</a> // <a href="http://example.com">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() 函數,咱們能夠在 PHP 輸出的時候爲 HTML 的連接或者表單代碼增長一個參數。有沒有想到什麼使用場景?POST 表單的 CSRF 攻擊的防範。
這個函數會根據 php.ini 文件中的 url_rewriter.tags 配置項來進行添加,在默認狀況下這個配置項只支持 from 表單,同時,它還能夠支持 a 標籤的href 、 area標籤的href 、 frame標籤的src 、 input標籤的src 等等。也就是說,會在這些標籤相對應的屬性中自動添加字段。固然,它也有一個反函數 output_reset_rewrite_vars() 用於取消以前增長的這個參數。
關於輸出緩衝控制這塊還有不少好玩的東西,不過限於篇幅咱們先介紹到這裏,未來踫到什麼好的功能的應用咱們再單獨講解。如今基於 Swoole 的應用愈來愈多,當咱們須要將 TP 、 Laravel 這類傳統框架轉換成支持 Swoole 的時候,每每就須要在入口文件使用輸出緩衝控制來進行修改。由於傳統框架基本都是直接進行 echo 之類的輸出的,而在 Swoole 中,echo 這類的內容是直接打印在控制檯的,這就須要咱們經過 ob_get_contents() 能力得到所有的輸出再經過 response->end() 來進行實際的響應。另外,還有一些其餘的場景也會用到輸出緩衝控制:
最後,再給出輸出緩衝控制相關的函數說明,具體內容你們仍是要多看官方文檔的介紹。
測試代碼:
參考文檔:
https://www.php.net/manual/zh/ref.outcontrol.php
https://www.php.net/manual/zh/session.configuration.php#ini.url-rewriter.tags
https://blog.csdn.net/xiaofan1988/article/details/43124359
===========
各自媒體平臺都可搜索【硬核項目經理】