1. 程式人生 > 程式設計 >PHP中的輸出緩衝控制詳解

PHP中的輸出緩衝控制詳解

php 中,我們直接進行 echo 、 或者 print_r 的時候,輸出的內容就會直接打印出來。但是,在某些情況下,我們並不想直接列印,這個時候就可以使用輸出緩衝控制來進行輸出列印的控制。當然,這一套功能並不僅限出針對列印的內容,我們還可以做其它一些操作,這個我們放到最後再說。

清除輸出

首先,我們先來看看不讓 echo 之類的內容列印輸出。

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() ,則不會有任何輸出了。它們三個的作用都是清除輸出緩衝區的內容。具體的區別大家可以參考文章最後給出的函式說明或者官方文件。

獲得輸出緩衝區的內容

ob_start();
echo 111,PHP_EOL;
$v = ob_get_contents();
ob_end_clean();

echo $v;

上面說過,使用了 ob_end_clean() 就會清除輸出緩衝區裡面的內容,但是在這段程式碼中,我們使用 ob_get_contents() 函式直接將緩衝區的內容賦值給了變數 \v 。這時候,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;
flush();
ob_flush();

類似的,我們在緩衝區中想要再次直接輸出內容,使用 flush() 、ob_flush()程式設計客棧 、 ob_end_flush() 及 ob_get_flush() 就可以了,其實就是相當於讓 ob_start() 之後的 echo 這類輸出語句重新生效並正常輸出。

另外,我們還可以使用一個函式進行自動的重新整理。

ob_implicit_flush();

ob_start();
echo 111,PHP_EOL;

使用 ob_implicit_flush() 之後,我們就不需要手動地呼叫 ob_flush() 之類的函式來重新整理緩衝區內容了。

一些檢測函式

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() 函式是緩衝區的狀態資訊,欄位的說明可以檢視官方文件,這裡不再贅述。

使用 ob_start() 的回撥函式來進行輸出緩衝區的內容替換

這是一個例子,但是可以推廣到其他很功能,比如我們可以用來進行全域性的輸出過濾、可以做 cssjs 檔案的壓縮優化等等。

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 內容。

新增 URL程式設計客棧 重寫器

output_add_rewrite_var('var','value');
// some links
echo '<a href="file.php" rel="external nofollow" >link</a>
<a href="http://example.com" rel="external nofollow"  rel="external nofollow" >link2</a>';

// <a href="file.php?var=value" rel="external nofollow" >link</a>
// <a href="http://example.com" rel="external nofollow"  rel="external nofollow" >link2</a>

// a form
echo '<form action="soCAYNcript.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 oCAYN配置項來進行新增,在預設情況下這個配置項只支援 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() 來進行實際的響應。另外,還有一些其他的場景也會用到輸出緩衝控制:

1.在PHP中,像header(),session_start(),setcookie() 等這樣的傳送標頭檔案的函式前,不能有任何的輸出,而利用輸出緩衝控制函式可以在這些函式前進行輸出而不報錯
2.對輸出的內容進行處理,例如生成靜態快取檔案、進行gzip壓縮輸出,這算是較常用的功能了
3.捕獲一些不可獲取的函式輸出,例如phpinfo(),var_dump() 等等,這些函式都會將運算結果顯示在瀏覽器中,而如果我們想對這些結果進行處理,則用輸出緩衝控制函式是個不錯的方法。說的通俗點,就是這類函式都不會有返回值,而要獲取這些函式的輸出資料,就要用到輸出緩衝控制函式
4.對一些資料進行實時的輸出
最後,再給出輸出緩衝控制相關的函式說明,具體內容大家還是要多看官方文件的介紹。

  • flush — 重新整理輸出緩衝
  • ob_clean — 清空(擦掉)輸出緩衝區
  • ob_end_clean — 清空(擦除)緩衝區並關閉輸出緩衝
  • ob_end_flush — 沖刷出(送出)輸出緩衝區內容並關閉緩衝
  • ob_flush — 沖刷出(送出)輸出緩衝區中的內容
  • ob_get_clean — 得到當前緩衝區的內容並刪除當前輸出緩。
  • ob_get_contents — 返回輸出緩衝區的內容
  • ob_get_flush — 刷出(送出)緩衝區內容,以字串形式返回內容,並關閉輸出緩衝區。
  • ob_get_length — 返回輸出緩衝區內容的長度
  • ob_get_level — 返回輸出緩衝機制的巢狀級別
  • ob_get_status — 得到所有輸出緩衝區的狀態
  • ob_gzhandler — 在ob_start中使用的用來壓縮輸出緩衝區中內容的回撥函式。ob_start callback function to gzip output buffer
  • ob_implicit_flush — 開啟/關閉絕對刷送
  • ob_list_handlers — 列出所有使用中的輸出處理程式。
  • ob_start — 開啟輸出控制緩衝
  • output_add_rewrite_var — 新增URL重寫器的值(Add URL rewriter values)
  • output_reset_rewrite_vars — 重設URL重寫器的值(Reset URL rewriter values)

測試程式碼:

github.com/zhangyue050…

以上就是PHP中的輸出緩衝控制詳解的詳細內容,更多關於PHP 輸出緩衝控制的資料請關注我們其它相關文章!