PHP有很多機制、函數,其實就是魔術師,重複發揮好,其實甚至是簡單應用,就會出現神奇的效果。兄弟連PHP訓練
這裡來講一個ob_start()函數。
ob_start()函數用於打開緩衝區,比如header()函數之前如果就有輸出,包括回車空格換行都會有”Header had all ready send by”的錯誤,這時可以先用ob_start()打開緩衝區PHP程式碼的資料塊和echo()輸出都會進入緩衝區而不會立刻輸出.當然打開緩衝區的作用很多,只要發揮你的想像.可以總結以下四點:
1.用於header( )之前
ob_start(); //打開緩衝區
echo ”Hellon”; //輸出
header(”location:index.”); ();//輸出全部內容到瀏覽器
?>
2.phpinfo()函數可取得客戶端和伺服器端的資訊,但要保存客戶端資訊用緩衝區的方法是最好的選擇.
ob_start(); //開啟緩衝區
phpinfo(); //使用phpinfo函數
$info=ob_get_contents(); //得到$編號的內容並且賦值給$ info.txt','w');//開啟檔案info.txt
fwrite($file,$info); //寫入訊息到info.txt
fclose($file); //關閉檔案infoinfo .txt
?>
3.靜態頁技術
ob_start();//開啟緩衝區
㟎php ob_start();//打開緩衝區 $content =ob_get_contents();//取得php頁面輸出的全部內容
$fp =fopen(”output00001.html”, “w”); //建立一個文件,並且打開,準備寫入
fwrite($fp, $content); //把php頁面的內容全部寫入output00001.html,然後…
fclose($fp);
?>
『4.輸出碼 If($code) {
ob_start( );
eval($code);
$contents =ob_get_contents();
ob_end_clean();
ob_end_clean();
〜<} ”;
exit();
}
return $contents;
}
Output Control 函數可以讓你自由控制腳本中資料的輸出。它非常有用,特別是對於:當你想在資料已經輸出後,再輸出檔案頭的情況。輸出控制函數不對使用 header() 或 setcookie(), 發送的檔案頭資訊產生影響,只對那些類似於 echo() 和PHP 程式碼的資料區塊有作用。
我們先舉一個簡單的例子,讓大家對OutputControl有一個大致的印象:
Example 1.
CODE『 ”Hellon”; / /輸出
header(”location:index.php”);//把瀏覽器重新導向)函數有了解的人都知道,這個函數會發送一段文件頭給瀏覽器,但是如果在使用這個函數之前已經有了任何輸出(包括空輸出,比如空格, 回車和換行)就會提示出錯。如果我們去掉第一行的ob_start(),再執行此程序,我們會發現得到了一條錯誤提示:”Header hadall ready send by”!但是加上ob_start,就不會提示出錯,原因是當打開了緩衝區,echo後面的字元不會輸出到瀏覽器,而是保留在伺服器,直到你使用flush或ob_end_flush才會輸出,所以不會有任何文件頭輸出的錯誤!
一、相關函數簡介:
1、Flush:刷新緩衝區的內容,輸出。
函數格式:flush()
說明:這個函數常用,效率很高。
2、ob_start:開啟輸出緩衝區
函數格式:void ob_start(void)
函數格式:void ob_start(void)
子說明:當緩衝區已啟動時,所有來自PHP程式
區。為了輸出緩衝區的內容,可以使用ob_end_flush()或flush()輸出緩衝區的內容。
3 、ob_get_contents:傳回內部緩衝區的內容。
使用方法:stringob_get_contents(void)
說明:此函數會傳回目前緩衝區中的內容,如果輸出緩衝區沒有激活,則傳回 FALSE 。
4、ob_get_length:傳回內部緩衝區的長度。
使用方法:intob_get_length(void)
說明:這個函數會傳回目前緩衝區中的長度;和ob_get_contents一樣,如果輸出緩衝區沒有啟動。則回傳 FALSE。
5、ob_end_flush:傳送內部緩衝區的內容到瀏覽器,並且關閉輸出緩衝區。
使用方法:voidob_end_flush(void)
說明:這個函數會傳送輸出緩衝區的內容(如果有的話)。
6、ob_end_clean:刪除內部緩衝區的內容,並且關閉內部緩衝區
使用方法:voidob_end_clean(void)
! 、ob_implicit_flush:開啟或關閉絕對刷新
使用方法:void ob_implicit_flush([int flag])
使用方法:void ob_implicit_flush([int flag])
說明:使用過Perl的人都知道$|=x的意義,這個字串可以關閉/=x的意義關閉/=x ob_implicit_flush函數也和那個一樣,預設為關閉緩衝區,開啟絕對輸出後,每個腳本輸出都直接送到瀏覽器,不再需要呼叫flush()
二、深入了解:
1. :
這個函數在PHP3中就出現了,是一個效率很高的函數,他有一個非常有用的功能就是刷新browser的cache.我們舉一個運作效果非常明顯的例子來說明flush.
2 Example 2 Example .
CODE
for($i = 1; $i
/一定的大小才能從瀏覽器輸出
// 換言之,如果cache的內容不達到一定的大小,它是不會在程式執行完畢前輸出的。經
// 過測試,我發現這個大小的底限是256個字元長。這表示cache以後收到的內容都會
// 源源不絕的被送出去。
For($j = 1; $j
echo $j.」
「;
ache🀎去,顯示到瀏覽器上
sleep(1); //讓程式」睡」一秒鐘,會讓你把效果看得更清楚
}
〕看http://www.php2000.com/~uchinaboy/out.php
PHP2000的最新的PHP聊天室就是用的這個技術,可惜的是原始碼未公開L
ob_implicit_flush()打開絕對刷新,就可以在程式中不再使用flush(),這樣做的好處是:提高效率!
2. 關於ob系列函數:
我想先引用我的好朋友y10k範例:
Example 3.
例如你用得到伺服器和客戶端的設定訊息,但是這個資訊會因為客戶端的不同而不同,如果想要保存phpinfo()函數的輸出怎麼辦?之前,可以說一點辦法也沒有,但是有了緩衝區的控制,我們可以輕鬆的解決:
CODE
ob_start(); //打開緩衝區
ob_start(); //打開緩衝區>函數
$info=ob_get_contents(); //得到緩衝區的內容並且賦值給$info
$file=fopen('info.txt','w');//開啟檔案. ($file,$info); //寫入資訊到info.txt
fclose($file); //關閉檔案info.txt
?>
資訊保存下來,這在以前恐怕沒有辦法辦到!其實上面就是將一些”過程”轉化為”函數”的方法!
或許有人會問:”難道就這個樣子嗎?還有沒有其他用途?”當然有了,例如筆者論壇的PHP 語法加亮顯示就和這個有關(PHP預設的語法加亮顯示函數會直接輸出,不能保存結果,如果在每次呼叫都顯示恐怕會很浪費CPU,筆者的論壇就把語法加亮函數顯示的結果用控制緩衝區的方法保留了),大家如果有興趣的話可以來看看http://www.zphp.com/bbs/!
可能現在大家對ob_start()的功能有了一定的了解,上面的一個例子看似簡單,但實際上已經掌握了使用ob_start()的要點。
.使用ob_start開啟browser的cache,這樣可以確保cache的內容在你呼叫flush(),ob_end_flush()(或程式執行完畢)之前不會被輸出。
.現在的你應該知道你所擁有的優勢:可以在任何輸出內容後面使用header,setcookie以及session,這是ob_start一個很大的特點;也可以使用ob_start的參數,在cache被寫入後,然後自動執行指令,例如ob_start(”ob_gzhandler 「);而我們最常用的做法是用ob_get_contents()得到cache中的內容,然後再進行處理…
.當處理完畢後,我們可以使用各種方法畢輸出,flush(),ob_end_flush(),以及等到程式執行完畢後的自動輸出。當然,如果你用的是ob_get_contents(),那麼就要你自己控制輸出方式了。
來,讓我們看看能用ob系列函數做些什麼…
一、 靜態模版技術
簡介:所謂靜態模版技術就是透過某種方式,使得使用者在cliclient端得到的是由PHPent端產生的html頁面。如果這個html頁面不會再更新,那麼當另外 的使用者再次瀏覽此頁面時,程式將不會再呼叫PHP以及相關的資料庫,對於某些資訊量比較大的網站,例如sina,163,sohu。類似這種的技術帶來的 好處是非常巨大的。
我所知道的實作靜態輸出的有兩種方法:
.透過y10k修改的phplib的一個叫做template.inc.php類別實作。
.使用ob系列函數實作。
對於第一種方法,因為不是這篇文章所要研究的問題,所以不再贅述。
我們現在來看看第二種方法的具體實作:
Example 4.
CODE php頁面的全部輸出
$content =ob_get_contents();//取得php頁面輸出的全部內容
$fp =fopen(”output00001.html", “一個寫檔”; //入
fwrite($fp, $content); //把php頁的內容全部寫入output00001.html,然後…
fclose($fp);
fclose($fp);.很容易的被實現了…
二、 捕捉輸出
以上的Example 4.是一種最簡單的情況,你還可以在寫入前對$content進行操作…
你可以設法捕捉一些 關鍵字,然後去對它進行再處理,例如Example3.所述的PHP語法高亮顯示。我個人認為,這個功能是此函數最大的精華所在,它可以解決各種各樣的問題,但需要你有足夠的想像力…
Example 5.
CODE
CODE ) {
If($code) {
ob_start();
eval($code); 🎀 );
}else {
echo 「錯誤!沒有輸出”;
exit();
}
return $contents;
}
以上這個例子的用途不是很大,不過很典型$code的本身就是一個含有變量的輸出頁面,而這個例子用eval把$code中的變數替換,然後輸出結果再進行輸出捕捉,再一次的進行處理…
Example 6. 加快傳輸
CODE
_lic
『 );
function CheckCanGzip(){
global$HTTP_ACCEPT_ENCODING;
『『 return 0;
}
if(strpos($HTTP_ACCEPT_ENCODING , 'x-gzip') !== false) return ”x-gzip”;
if(strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false) return ”gzip";
functionGzDocOut($level=1,$debug=0){
$ENCODING = CheckCanGzip();
〜〜ING];
$Contents =ob_get_contents();
ob_end_clean();
if ($debug){
$s = ”
Notcompress length: 」.strlen($s);
Compressed length:”.strlen(gzcompress( $Contents,$level));
$Contents .= $s;
}
header(”Content-pcoding:$ENCODINGm”); 00x00×00”;
$ Size = strlen($Contents);
$Crc = crc32($Contents);
$Contents =gzcompress($Contents,$level);
$Contents = substr($Contents,0, strlen($Contents) – 4);
print $Contents;
print pack('V),$rc) pack );
exit;
}else{
ob_end_flush();
?>
這是catoc的一段很早以前的程式碼,是在weblogs.com看到的,他利用了zlib的函數,對傳輸的內容進行了壓縮,測試表明,對於10k以上的頁面,會產生效果,而且頁面越大,效果越明顯……