首頁 > 後端開發 > php教程 > 用PHP的ob_start;控制您的瀏覽器cache!

用PHP的ob_start;控制您的瀏覽器cache!

WBOY
發布: 2016-07-29 08:36:17
原創
909 人瀏覽過

【轉載】原文網址:http://www.itbbs.cn/index.php?showtopic=1074
    Output Control 函數可以讓你自由控制腳本中資料的輸出。它非常有用,特別是對於:當你想在資料已經輸出後,再輸出檔案頭的情況。輸出控制函數不對使用 header() 或 setcookie(), 發送的檔案頭資訊產生影響,只對那些類似於 echo() 和 PHP 程式碼的資料區塊有作用。
  我們先舉一個簡單的例子,讓大家對Output Control有一個大致的印象:
  Example 1.
   

<span><code><span><br>    <span><?php <BR>ob_start</SPAN><SPAN>(); </SPAN><SPAN>//打开缓冲区 <BR></SPAN><SPAN>echo </SPAN><SPAN>"Hellon"; //输出 <BR>header("</SPAN><SPAN>location</SPAN><SPAN>:</SPAN><SPAN>index</SPAN><SPAN>.</SPAN><SPAN>php</SPAN><SPAN>"); //把浏览器重定向到index.php <BR>ob_end_flush();//输出全部内容到浏览器 <BR>?> <br>    </span></span>    ob_start(); //開啟緩衝區  echo "Hellon"; //輸出  header("location:index.php"); //把瀏覽器重新導向到index.php  ob_end_flush();//輸出全部內容到瀏覽器  ?>     
  所有對header()函數有了解的人都知道,這個函數會發送一段文件頭給瀏覽器,但是如果在使用這個函數之前已經有了任何輸出(包括空輸出,比如空格,回車和換行)就會提示出錯。如果我們去掉第一行的ob_start(),再執行此程序,我們會發現得到了一條錯誤提示:"Header had all ready send by"!但加上ob_start,就不會提示出錯,原因是當開啟了緩衝區,echo後面的字元不會輸出到瀏覽器,而是保留在伺服器,直到你使用flush或ob_end_flush才會輸出,所以並不會有任何文件頭輸出的錯誤!
一、 相關函數簡介:
1、Flush:刷新緩衝區的內容,輸出。
函數格式:flush()
說明:這個函數常用,效率很高。
2、ob_start :開啟輸出緩衝區
函數格式:void ob_start(void)
說明:當緩衝區啟動時,所有來自PHP程式的非檔案頭資訊不會傳送,而是保存在內部緩衝區。為了輸出緩衝區的內容,可以使用ob_end_flush()或flush()輸出緩衝區的內容。
3 、ob_get_contents :傳回內部緩衝區的內容。
使用方法:string ob_get_contents(void)
說明:這個函數會傳回目前緩衝區中的內容,如果輸出緩衝區沒有激活,則傳回 FALSE 。
4、ob_get_length:傳回內部緩衝區的長度。
使用方法:int ob_get_length(void)
說明:這個函數會回傳目前緩衝區中的長度;和ob_get_contents一樣,如果輸出緩衝區沒有啟動。則回傳 FALSE。
5、ob_end_flush :傳送內部緩衝區的內容到瀏覽器,並且關閉輸出緩衝區。
使用方法:void ob_end_flush(void)
說明:這個函數會傳送輸出緩衝區的內容(如果有的話)。
6、ob_end_clean:刪除內部緩衝區的內容,並且關閉內部緩衝區
使用方法:void ob_end_clean(void)
說明:這個函數不會輸出內部緩衝區的內容而是把它刪除!
7、ob_implicit_flush:開啟或關閉絕對刷新
使用方法:void ob_implicit_flush ([int flag])
說明:使用過Perl的人都知道$|=x的意義,這個字串可以打開/關閉緩衝區,而ob_implicit_flush函數也和那個一樣,預設為關閉緩衝區,開啟絕對輸出後,每個腳本輸出都直接傳送到瀏覽器,不再需要呼叫flush()  
二、深入了解:
1. 關於Flush函數:
這個函數在PHP3中就出現了,是一個效率很高的函數,他有一個非常有用的功能就是刷新browser的cache.我們舉一個運行效果非常明顯的範例來說明flush.
Example 2.
<span><code><span><br><span><?php <BR></SPAN><SPAN>for(</SPAN><SPAN>$i </SPAN><SPAN>= </SPAN><SPAN>1</SPAN><SPAN>; </SPAN><SPAN>$i </SPAN><SPAN><= </SPAN><SPAN>300</SPAN><SPAN>; </SPAN><SPAN>$i</SPAN><SPAN>++ ) print(</SPAN><SPAN>" "</SPAN><SPAN>); <BR></SPAN><SPAN>// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 <BR>// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经 <BR>// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会 <BR>// 源源不断的被发送出去。 <BR></SPAN><SPAN>For(</SPAN><SPAN>$j </SPAN><SPAN>= </SPAN><SPAN>1</SPAN><SPAN>; </SPAN><SPAN>$j </SPAN><SPAN><= </SPAN><SPAN>20</SPAN><SPAN>; </SPAN><SPAN>$j</SPAN><SPAN>++) { <BR>echo </SPAN><SPAN>$j</SPAN><SPAN>.</SPAN><SPAN>" <BR>"</SPAN><SPAN>; <BR></SPAN><SPAN>flush</SPAN><SPAN>(); </SPAN><SPAN>//这一部会使cache新增的内容被挤出去,显示到浏览器上 <BR></SPAN><SPAN>sleep</SPAN><SPAN>(</SPAN><SPAN>1</SPAN><SPAN>); </SPAN><SPAN>//让程序"睡"一秒钟,会让你把效果看得更清楚 <BR></SPAN><SPAN>} <BR></SPAN><SPAN>?></span>  <br></span>for($i 1$i 300$i++ ) print(" "); // 這句話非常關鍵,cache的結構使得它的內容只有達到一定的大小才能從瀏覽器裡輸出  // 換言之,如果cache的內容不達到一定的大小,它是不會在程式執行完畢前輸出的。經  // 過測試,我發現這個大小的底限是256個字元長。這表示cache以後收到的內容都會  // 源源不絕的被送出去。 For($j 1$j 20$j++) {  echo $j."  " flush(); //這部會讓cache新增的內容被擠出去,顯示瀏覽器上  sleep (1); //讓程式"睡"一秒鐘,會讓你把效果看得更清楚  ?> 
註:如果在程式的首部加入ob_implicit_flush()開啟絕對刷新,就可以在程式中不再使用flush(),這樣做的好處是:提高效率!
2. 關於ob系列函數:
我想先引用我的好朋友y10k的一個例子:
Example 3.
例如你用得到伺服器和客戶端的設定訊息,但是這個訊息會因為客戶端的不同而不同,如果想要保存phpinfo()函數的輸出呢?在沒有緩衝區控制之前,可以說一點辦法也沒有,但是有了緩衝區的控制,我們可以輕鬆的解決:
<span><code><span><br><span><?php <BR>ob_start</SPAN><SPAN>(); </SPAN><SPAN>//打开缓冲区 <BR></SPAN><SPAN>phpinfo</SPAN><SPAN>(); </SPAN><SPAN>//使用phpinfo函数 <BR></SPAN><SPAN>$info</SPAN><SPAN>=</SPAN><SPAN>ob_get_contents</SPAN><SPAN>(); </SPAN><SPAN>//得到缓冲区的内容并且赋值给$info <BR></SPAN><SPAN>$file</SPAN><SPAN>=</SPAN><SPAN>fopen</SPAN><SPAN>('</SPAN><SPAN>info.txt</SPAN><SPAN>'</SPAN><SPAN>,</SPAN><SPAN>'</SPAN><SPAN>w</SPAN><SPAN>'</SPAN><SPAN>); //打开文件info.txt <BR>fwrite($file,$info); //写入信息到info.txt <BR>fclose($file); //关闭文件info.txt <BR>?>  <br></span></span>ob_start(); //開啟緩衝區 
phpinfo();  //使用phpinfo函數 
$info=ob_get_contents();  //得到緩衝區的內容並且賦值給$info 
$file=fopen ('info.txt','w'); //開啟檔案info.txt 
fwrite($file,$info); //寫入訊息到info.txt 
fclose($file); //關閉文件info.txt 
?> 


用以上的方法,就可以把不同用戶的phpinfo資訊保存下來,這在以前恐怕沒有辦法辦到!其實上面就是將一些"過程"轉換為"函數"的方法!
或許有人會問:"難道就這個樣子嗎?還有沒有其他用途?"當然有了,比如筆者論壇的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系列函數做些什麼…
一、靜態模版技術
簡介:所謂靜態模版技術就是透過某種方式,使得使用者在client端得到的是由PHP產生的html頁面。如果這個html頁面不會再更新,那麼當另外的使用者再次瀏覽此頁面時,程式將不會再呼叫PHP以及相關的資料庫,對於某些資訊量比較大的網站,例如sina,163,sohu。類似這種的技術帶來的好處是非常巨大的。 <span><br><span><?php <BR>ob_start</SPAN><SPAN>();</SPAN><SPAN>//打开缓冲区 <BR></SPAN><SPAN>?></span>  <br>php页面的全部输出  <br><span><? <BR>$content </SPAN><SPAN>= </SPAN><SPAN>ob_get_contents</SPAN><SPAN>();</SPAN><SPAN>//取得php页面输出的全部内容 <BR></SPAN><SPAN>$fp </SPAN><SPAN>= </SPAN><SPAN>fopen</SPAN><SPAN>(</SPAN><SPAN>"output00001.html"</SPAN><SPAN>, </SPAN><SPAN>"w"</SPAN><SPAN>); </SPAN><SPAN>//创建一个文件,并打开,准备写入 <BR></SPAN><SPAN>fwrite</SPAN><SPAN>(</SPAN><SPAN>$fp</SPAN><SPAN>, </SPAN><SPAN>$content</SPAN><SPAN>); </SPAN><SPAN>//把php页面的内容全部写入output00001.html,然后…… <BR></SPAN><SPAN>fclose</SPAN><SPAN>(</SPAN><SPAN>$fp</SPAN><SPAN>); <BR></SPAN><SPAN>?></span>  <br></span>我所知道的實作靜態輸出的有兩種方法: .透過y10k修改的phplib的一個叫template.inc.php類別實作。 .使用ob系列函數實作。 對於第一種方法,因為不是這篇文章所要研究的問題,所以不再贅述。 我們現在來看看第二種方法的具體實作: Example 4. <span><span><?php   <🎜>ob_start SPAN><span>();</span><span>//開啟緩衝區  </span><span>?></span>  php頁面的全部輸出  <span>   $content </span><span>= </span><span>ob_get_contents</span><span>();</span><span>//取得php頁面輸出的全部內容  </span><span>$fp </span><span>= </span><span>fopen</span><span>(</span><span>"output00001.html"</span><span>, </span><span>"w"</span><span>); </span><span>//建立文件,打開,準備寫入  </span> <span>fwrite</span><span>(</span><span>$fp</span><span>, </span><span>$content</span><span>); </span><span>//把php頁面的內容全部寫入output00001.html,然後…  </span><span>fclose</span><span>(</span><span>$fp<span>);  </span><span>?></span>  </span></span></span>
二、 捕捉輸出
以上的Example 4.是一種最簡單的情況,你還可以在寫入前對$content進行操作……
你可以設法捕捉一些關鍵字,然後去對它進行再處理,例如Example 3.所述的PHP語法高亮顯示。個人認為,這個功能是此函數最大的精華所在,它可以解決各種各樣的問題,但需要你有足夠的想像力…
Example 5.
<span><code><span><br><span><? <BR></SPAN><SPAN>Function </SPAN><SPAN>run_code</SPAN><SPAN>(</SPAN><SPAN>$code</SPAN><SPAN>) { <BR>If(</SPAN><SPAN>$code</SPAN><SPAN>) { <BR></SPAN><SPAN>ob_start</SPAN><SPAN>(); <BR>eval(</SPAN><SPAN>$code</SPAN><SPAN>); <BR></SPAN><SPAN>$contents </SPAN><SPAN>= </SPAN><SPAN>ob_get_contents</SPAN><SPAN>(); <BR></SPAN><SPAN>ob_end_clean</SPAN><SPAN>(); <BR>}else { <BR>echo </SPAN><SPAN>"错误!没有输出"</SPAN><SPAN>; <BR>exit(); <BR>} <BR>return </SPAN><SPAN>$contents</SPAN><SPAN>; <BR>} <BR></SPAN></SPAN>Function run_code($code< SPAN>) {  <🎜>If($code) {  <🎜>ob_start();  <🎜 >eval($code);  <🎜>$contents ob_get_contents< /SPAN>();  <🎜>ob_end_clean();  <🎜>}else {  <🎜>echo "錯誤!沒有輸出";  <🎜>exit();  <🎜>}  <🎜>return $contents;  <🎜>}  <🎜> <🎜>
以上這個例子的用途不是很大,不過很典型$code的本身就是一個含有變數的輸出頁面,而這個例子用eval把$code中的變數替換,然後對輸出結果再進行輸出捕捉,再一次的進行處理…
Example 6. 加速傳輸
<SPAN><BR><SPAN><? <BR></SPAN><SPAN>/* <BR>** Title.........: PHP4 HTTP Compression Speeds up the Web <BR>** Version.......: 1.20 <BR>** Author........: catoc <[email]catoc@163.net[/email]>  <br>** Filename......: gzdoc.php  <br>** Last changed..: 18/10/2000  <br>** Requirments...: PHP4 >= 4.0.1  <br>** PHP was configured with --with-zlib[=DIR]  <br>** Notes.........: Dynamic Content Acceleration compresses  <br>** the data transmission data on the fly  <br>** code by sun jin hu (catoc) <[email]catoc@163.net[/email]>  <br>** Most newer browsers since 1998/1999 have  <br>** been equipped to support the HTTP 1.1  <br>** standard known as "content-encoding."  <br>** Essentially the browser indicates to the  <br>** server that it can accept "content encoding"  <br>** and if the server is capable it will then  <br>** compress the data and transmit it. The  <br>** browser decompresses it and then renders  <br>** the page.  <br>**  <br>** Modified by John Lim ([email]jlim@natsoft.com.my[/email])  <br>** based on ideas by Sandy McArthur, Jr  <br>** Usage........:  <br>** No space before the beginning of the first '<?' tag. <BR>** ------------Start of file---------- <BR>** |<? <BR>** | include('gzdoc.php'); <BR>** |? >  <br>** |<HTML>  <br>** |... the page ...  <br>** |</HTML>  <br>** |<? <BR>** | gzdocout(); <BR>** |? >  <br>** -------------End of file-----------  <br>*/  <br></span><span>ob_start</span><span>();  <br></span><span>ob_implicit_flush</span><span>(</span><span>0</span><span>);  <br>function </span><span>CheckCanGzip</span><span>(){  <br>global </span><span>$HTTP_ACCEPT_ENCODING</span><span>;  <br>if (</span><span>headers_sent</span><span>() || </span><span>connection_timeout</span><span>() || </span><span>connection_aborted</span><span>()){  <br>return </span><span>0</span><span>;  <br>}  <br>if (</span><span>strpos</span><span>(</span><span>$HTTP_ACCEPT_ENCODING</span><span>, '</span><span>x-gzip</span><span>'</span><span>) !== false) return "x-gzip";  <br>if (strpos($HTTP_ACCEPT_ENCODING,</span><span>'</span><span>gzip</span><span>'</span><span>) !== false) return "gzip";  <br>return 0;  <br>}  <br>/* $level = compression level 0-9, 0=none, 9=max */  <br>function GzDocOut($level=1,$debug=0){  <br>$ENCODING = CheckCanGzip();  <br>if ($ENCODING){  <br>print "n<!-- Use compress $ENCODING -->n";  <br>$Contents = ob_get_contents();  <br>ob_end_clean();  <br>if ($debug){  <br>$s = "<p>Not compress length: ".strlen($Contents);  <br>$s .= "  <br>Compressed length: ".strlen(gzcompress($Contents,$level));  <br>$Contents .= $s;  <br>}  <br>header("Content-Encoding: $ENCODING");  <br>print "x1fx8bx08x00x00x00x00x00";  <br>$Size = strlen($Contents);  <br>$Crc = crc32($Contents);  <br>$Contents = gzcompress($Contents,$level);  <br>$Contents = substr($Contents, 0, strlen($Contents) - 4);  <br>print $Contents;  <br>print pack(</span><span>'</span><span>V</span><span>'</span><span>,$Crc);  <br>print pack(</span><span>'</span><span>V</span><span>'</span><span>,$Size);  <br>exit;  <br>}else{  <br>ob_end_flush();  <br>exit;  <br>}  <br>}  <br>?>  <br></span></span>
這是catoc的一段很早以前的程式碼,是在weblogs.com看到的,他利用了zlib的函數,對傳輸的內容進行了壓縮,測試表明,對於10k以上的頁面,會產生效果,而且頁面越大,效果越明顯…

以上就介紹了 用PHP的ob_start;控制您的瀏覽器cache!,包括了方面的內容,希望對PHP教程有興趣的朋友有所幫助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板