首頁  >  文章  >  後端開發  >  詳解PHP中的輸出緩衝控制(Output Control)

詳解PHP中的輸出緩衝控制(Output Control)

青灯夜游
青灯夜游轉載
2021-06-21 18:23:183677瀏覽

本篇文章帶大家來了解PHP中的輸出緩衝控制(Output Control) 。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

詳解PHP中的輸出緩衝控制(Output Control)

在 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;
echo "aaaa", 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;
echo "aaaa", 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;
echo "aaaa", 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() 的回呼函數來進行輸出緩衝區的內容替換

這是一個例子,但是可以推廣到其他很功能,例如我們可以用來進行全域的輸出過濾、可以做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 內容。

新增 URL 重寫器
output_add_rewrite_var('var', 'value');
// some links
echo &#39;<a href="file.php">link</a>
<a href="http://example.com">link2</a>&#39;;

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

// a form
echo &#39;<form action="script.php" method="post">
<input type="text" name="var2" />
</form>&#39;;

// <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() 来进行实际的响应。另外,还有一些其他的场景也会用到输出缓冲控制:

  • 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)
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202005/source/%E8%BF%98%E6%90%9E%E4%B8%8D%E6%87%82PHP%E4%B8%AD%E7%9A%84%E8%BE%93%E5%87%BA%E7%BC%93%E5%86%B2%E6%8E%A7%E5%88%B6%EF%BC%9F.php

推荐学习:《PHP视频教程

以上是詳解PHP中的輸出緩衝控制(Output Control)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除