$7.49 .com domain with free InstantPage Website Builder$1.99 Web Hosting   捷飞网络官方淘宝店   Godaddy 优惠码
返回列表 发帖
分享到:




[PHP 语言] 分享简析php之ob_start函数的用途

本帖最后由 jim9 于 2011-8-28 06:46 编辑 1 U% {9 E$ y* O; i6 V! |

* |6 L% H4 A2 W; k# ^& g& L: I我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
4 m& Z0 I( A) l: Z/ PExample 1. 8 K3 `2 o# }7 s# R" j; R0 W
----------------------------
+ @9 i& C2 n4 C5 V  f+ [( M# ^----------------------------
' d2 u3 P, q3 P9 m) Vob_start(); //打开缓冲区 6 }' e3 V/ t0 b8 \3 n6 T
echo "Hello\n"; //输出
9 I. G. D1 D' g) X* pheader(“location:index.php”); //把浏览器重定向到index.php 2 y* V' j5 A$ R& G) E# _. H
ob_end_flush();//输出全部内容到浏览器
6 P9 {7 w8 m1 C2 g/ M2 N3 F?> % C' x9 M; L- h/ L: P
-----------------------
: ?' F9 Y" D) z5 y3 S. T! ~  r-----------------------
! H9 x3 D# H! E% q& X# m/ m所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 1 i5 b, ?7 u( P
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 4 W( M2 A# d. p7 @3 Q& g
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had
4 D7 k6 X1 _( M, G) T: vall ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误! 5 \3 b5 l( q8 e

: N3 c8 t2 p2 i9 r4 z/ V( p2 ~6 `8 @一、 相关函数简介:
4 Y2 \! S& `9 R$ @1 V  d1、Flush:刷新缓冲区的内容,输出。
8 z* X( i8 J9 v# j函数格式:flush() + P) I0 y' b; ^  e6 l6 O
说明:这个函数经常使用,效率很高。 ( b3 Y' \4 {& @  ]
2、ob_start :打开输出缓冲区
# M* G' g# y# Z函数格式:void ob_start(void) - `3 f4 {3 k: d# z. c- k& {
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
  O1 x% `  Y& @为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。 ) M8 P. P/ M* Q
3 、ob_get_contents :返回内部缓冲区的内容。
+ {2 M/ E# _8 u8 t使用方法:string ob_get_contents(void) # x  L0 t' [. L8 p
说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
+ v0 |7 j: r$ r8 m4、ob_get_length:返回内部缓冲区的长度。 5 y" E; `- s* Z0 W
使用方法:int ob_get_length(void)
/ b' {% J) b4 V3 r) O说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
" z# |2 W" u* j- F  q: T- d/ ^活。则返回 FALSE。 ) W) z, D: m2 a
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。 * h9 J8 u; x4 R0 O9 |6 }
使用方法:void ob_end_flush(void) 4 f' ]- U# O2 v) Z8 W! |
说明:这个函数发送输出缓冲区的内容(如果有的话)。
9 Y/ }) ~* X6 L7 t; w6 v6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
' b, O# X7 z, F* z  L使用方法:void ob_end_clean(void) 4 N1 v7 _, p8 ^
说明:这个函数不会输出内部缓冲区的内容而是把它删除! ( o" |) A# g4 z! O, I! l
7、ob_implicit_flush:打开或关闭绝对刷新 : g( e/ b/ M  E1 e5 J5 Z3 \
使用方法:void ob_implicit_flush ([int flag])
( `4 I  b; S/ H" O7 Q4 ]说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而 $ O" F! e% Z2 u5 c8 A
ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
  H/ Y& f% F/ [6 C' t9 \/ ^接发送到浏览器,不再需要调用 flush() ) |" m2 T0 {* z9 w  |) _6 B3 Y/ \; [
; L; F7 g9 A% C- h- G6 E1 a
二、深入了解: , A/ V# h3 d5 r  P4 G
1. 关于Flush函数: / F6 \! q6 t$ c3 x1 w' N7 J
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser # `5 R$ v, T' }; T" e
的cache.我们举一个运行效果非常明显的例子来说明flush.
6 J. @+ b  z4 DExample 2. # V  L! v7 k; o
---------------------------------
% v  p7 f0 o1 ?# n  T---------------------------------
0 j6 ~5 g0 z  F1 u5 f: b% X8 K: T. Lfor( = 1; <= 300; ++ ) print(“ “);
6 b4 U8 F& u% i! X. @// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 8 l. X) t1 I0 K! E
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
, l4 x: y3 F+ I6 N9 ?0 P// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
& Y+ t! C, L7 a+ a  \: a// 源源不断的被发送出去。 ( K6 c& L, j3 R
For( = 1; <= 20; ++) { - J! x3 P7 J, \/ g1 L9 f
echo .”
* d* a; L5 S8 G/ A& W% J”;
3 {& `. n. \7 H$ p8 O8 hflush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
: q' _1 y% w! B2 U1 p: N& jsleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚
9 S- W/ t* b) T( f0 ^% h} 4 G$ @2 v$ x7 v1 q6 |" z
?>
& v! z: E- L# u--------------------------------- & v- w% f( K9 t' t
--------------------------------- 7 y) y$ h0 V. L$ Q
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
# H1 W3 O2 ?( q% z. `! dPHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L . B) o- @, L, q2 M1 ]) f  p
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush , `. _% Z: c5 X! S
(),这样做的好处是:提高效率! + g& d( [% q6 ^/ E9 t% l1 O
2. 关于ob系列函数: ) R" A$ o: \0 T7 G$ E
我想先引用我的好朋友y10k的一个例子: . F* E3 f' ~6 C
Example 3.
6 K. P5 [& h" K1 N; J---------------------------------
. [4 M; s3 @* k--------------------------------- % f3 D6 q! c( t4 I3 l2 I% ]! A
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
0 r) v/ c; l! X保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 . b' G' @- [8 j9 z9 I: E- D
缓冲区的控制,我们可以轻松的解决:
: z# E  S) [- [8 n----------------------------
1 H- H0 }, B2 p5 mob_start(); //打开缓冲区
/ q  W5 q- W! m1 k% j! c+ M0 @phpinfo(); //使用phpinfo函数
4 X' U! P- X8 G( I$ u  S=ob_get_contents(); //得到缓冲区的内容并且赋值给
0 S' t$ t1 x0 m( X8 g=fopen('info.txt','w'); //打开文件info.txt 9 G6 u4 p& o$ y$ J# K* {6 v
fwrite(,); //写入信息到info.txt 8 C# y- n2 M( f3 P3 i' P- y4 X/ Y! b
fclose(); //关闭文件info.txt & L1 n/ J& n2 Q( D  l1 N, x6 W
?>
7 J  g5 [0 N$ k0 w- l-------------------------
& j' u. ?; v# w用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上
: {0 Q+ q1 g; a; |面就是将一些“过程”转化为“函数”的方法! , j: {  I7 t6 |" Z

# h$ w) X" J( [! v& O& x或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语   x# R+ Q* t; D# c/ ]8 }- ]
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
6 J5 N' k" E  s8 Z# |调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
3 J6 R1 e- p/ ]1 T3 R+ i9 K了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com// T; c2 ~* A3 ^- O/ B$ K
-------------------------------
- _) U# u; U1 F: a4 i------------------------------- / n0 Z: l5 l0 _% }$ D/ d  }
可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌
  f8 y3 ^, Q1 d+ H+ \握了使用ob_start()的要点。 ' u8 `, e, J: y6 e, Q9 c% m" U
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush 6 t* x/ ~4 I2 j& z7 ?$ p
(),ob_end_flush()(或程序执行完毕)之前不会被输出。
  V" K4 x# x  p7 R4 E+ i, U8 S<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 $ ?6 |1 u0 }& f/ M4 k' e
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后 4 r: Z+ |" v" z: X- a7 {* B
自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得
4 U1 p6 r" s# w$ S/ N5 J8 E2 l到cache中的内容,然后再进行处理…… - d5 n( K3 E, R( J' C
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 # z+ n! P& ?6 f8 R
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。
- D/ e+ e8 Y+ z) L3 f4 P来,让我们看看能用ob系列函数做些什么……
& r4 B; t! w, S, p一、 静态模版技术
; i$ [! l5 s7 ?! G& i, {简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页
* b3 U: q) f/ p$ v8 p4 v& V面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用 4 [, t. g) |5 }( F- E( H( y+ y. V
PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 0 m% b/ w7 m$ b: z0 L$ C# D2 l7 R
来的好处是非常巨大的。 7 W% E! b# d; Y! w
我所知道的实现静态输出的有两种办法: ! A. \" d# D. G( K+ r# b" i, T% G' O
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
3 u1 J6 i  u+ U4 ~# ]% D: C<2>.使用ob系列函数实现。
2 q8 H) a  z, L# r5 l+ u5 N对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
  `9 a4 {+ M. `. J' Y我们现在来看一看第二种方法的具体实现:
- t9 S: _+ T! wExample 4.
, ~9 w3 Q2 I4 M; t4 ^5 u0 y--------------------------------- " W, W8 m, I$ o3 i) W+ M
--------------------------------- . W' [7 G7 X5 d
ob_start();//打开缓冲区 ) @3 d# h' `  x
?> ; G" s$ T! L5 w" O$ t. j
php页面的全部输出 ( M5 k& e0 U0 W" b- T, _! j
= ob_get_contents();//取得php页面输出的全部内容 3 X& v$ p" k0 q
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
% D  b5 S: ?. u, Y9 S' w0 f) Zfwrite(, ); //把php页面的内容全部写入output00001.html,然后……
0 d  v* a: N4 C6 b9 rfclose();
8 a: k& M$ U/ a$ \* s  j2 A/ g8 [- @?> & K( ~  ?' j0 r& E$ C
--------------------------------- 0 d' o3 T/ W  }  w9 D- e
--------------------------------- & O) G! S" E$ c  x
这样,所谓的静态模版就很容易的被实现了……
8 d! w( P* S4 Q, X: U) v二、 捕捉输出 8 {2 A& O4 V! t
以上的Example 4.是一种最简单的情况,你还可以在写入前对
( V% l! x& e' D; v! k你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 . Y4 k, E9 g1 I3 Z4 D: u; d4 b
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
3 G: P% ~6 D  M0 l9 D想象力…… & `/ @% {+ L7 f( F; U8 j9 B3 h
Example 5.
7 I4 T/ H, x5 K6 y0 E3 s) T---------------------------------
& t9 a, t+ ^2 L+ q+ t( x--------------------------------- " V4 G! ^% m6 M+ Y7 J8 [
Function run_code() {
8 V. X6 I2 g; \0 uIf() {
1 i+ e4 H( w; O3 a# N; f" }+ Nob_start();
3 {( s! Q5 p1 H& g* [1 t3 Keval(); / h: \2 V/ l7 y, j) Y
= ob_get_contents();
. n" R  T7 v# x2 {ob_end_clean();
( G6 Y6 {0 \1 \: A; Y}else {
. F, ?/ N) C$ Q; l3 z2 ]( l- G$ R, vecho “错误!没有输出”; & G$ F& V7 ]" _' z7 `
exit();
' \  N" a! ^0 n. S/ L}
5 F0 a3 h: o# t! _8 }% [1 mreturn ;
0 V5 g: X) a* O! _7 _1 e} * H" M5 {1 v! ~8 q% A- E. Y4 Y
-------------------------------- / I, _4 w' [6 n$ l2 O/ r- z
--------------------------------- : w" Z+ T# T0 E8 q" |& K) V6 ~3 i# D
以上这个例子的用途不是很大,不过很典型
+ }% o. S5 {! X/ a. m. `子用eval把 3 A" C- D1 G3 J: V: `
Example 6. 加快传输 , I" G" Y4 g% n1 r+ O$ V% {
--------------------------------- - g% ]$ b8 v( M) s5 l
--------------------------------- ) q" \" q, \+ A
/*
2 F/ I9 R3 _+ \0 t" D7 a  |* i3 h** Title.........: PHP4 HTTP Compression Speeds up the Web
% v/ S; h" w" r7 Y/ ~, `& L9 o' k2 z9 v** Version.......: 1.20 - |  W4 u9 j/ |) w5 @7 i- H
** Author........: catoc
8 g# X) G. }) p! ?: Z** Filename......: gzdoc.php ) l9 \& W1 h: ~4 C
** Last changed..: 18/10/2000 4 R) L, f$ @# \: I; F1 z; v4 ]. B! w
** Requirments...: PHP4 >= 4.0.1
6 ?! b1 f! x  e7 ~2 N** PHP was configured with --with-zlib[=DIR] $ A" _5 B: w  C) ]
** Notes.........: Dynamic Content Acceleration compresses " o1 e$ l$ Z, o) k# M0 G7 p: t
** the data transmission data on the fly
& T; H4 O+ x0 E! i1 g! |** code by sun jin hu (catoc) . y" U' S. M( S0 [
** Most newer browsers since 1998/1999 have   k; G, o  s. z
** been equipped to support the HTTP 1.1 ; r  Q* C$ L5 w) O* O
** standard known as "content-encoding."
/ K2 T. D$ w& y& l. o** Essentially the browser indicates to the
/ j9 J7 L7 c; E* R5 Z: S** server that it can accept "content encoding"
+ T' Z- w3 d# k9 \$ Y** and if the server is capable it will then
3 |7 D3 E. ^2 d$ @, F( I9 i** compress the data and transmit it. The
, \8 A1 ?) f1 p) ]$ Y** browser decompresses it and then renders
" ~( x1 s" `0 T/ u( \4 ~: t** the page. 5 H& P( F. u/ _% M- G
**
; E( X3 [/ d( D** Modified by John Lim (jlim@natsoft.com.my) 7 B' T( D1 S' J9 k& }3 t" c
** based on ideas by Sandy McArthur, Jr
; R/ w* j6 X) T# I( \** Usage........:
" K8 M2 q4 |" D9 V0 E** No space before the beginning of the first ' ** ------------Start of file---------
" l$ Q& ~' g7 T% y7 z-
/ C- y6 b6 \) X3 T6 F6 q! ?- |** │ ** │ include('gzdoc.php');
' j5 c# Z( p, p$ Z9 s** │? >
0 {. z4 s1 N0 O5 T** │
& T, u, ~: s. C- g** │... the page ... 1 c& c1 Y' ^4 r) V9 W! F
** │
1 K& Q- }: v7 D' D+ C, k** │ ** │ gzdocout(); ! U: b" F! R3 E4 }, u
** │? >
7 T7 z" y7 ]) V* @** -------------End of file----------- : B. p! ~; C$ I' j# t" c. l
*/ * L4 I# e7 \* o; w! J, v& I" p/ M
ob_start();
7 W% T$ R* g% j3 Xob_implicit_flush(0);
9 X8 M$ |# p7 g' Wfunction CheckCanGzip(){
: |: s  S9 ]  X1 o" Oglobal ;
( R7 G, `) P; j5 k4 @  Q, ~% ~if (headers_sent() ││ connection_timeout() ││ connection_aborted()){ # X; ]: N( a' }% h& k
return 0;
2 G8 h! ^- D( Q} : I& e! X& w( X8 _$ o0 |
if (strpos(, 'x-gzip') !== false) return "x-gzip";
. h' U# f/ x" f* \2 i+ Lif (strpos(,'gzip') !== false) return "gzip";
3 L+ V2 ?& X* W4 o! }return 0;
6 V1 D3 h/ H! U1 F4 v} 9 l2 O* e  @# U* l5 k! W# _
/* = compression level 0-9, 0=none, 9=max */
& k  S7 A' o! c( g) k7 ~) v# p2 Qfunction GzDocOut(=1,=0){
7 Q" F0 X/ Q( ]7 y, w= CheckCanGzip();
4 O2 m- A2 ]. W( v8 H/ H+ A0 t6 m- uif (){
& N$ N4 \+ o) t; Mprint "\n\n"; 0 ^! W" k* z* e- {; v
= ob_get_contents();
9 l+ o0 T# m$ zob_end_clean();
$ @% [2 n' G. w9 K6 w8 r/ {if (){ ( e3 B+ F* Z6 `8 T6 a" ?, E5 a+ {
= "
0 Y" D) h* i& x) F! rNot compress length: ".strlen();
  g1 x0 {7 p7 V  L: s- E.= " 6 J8 F' B% n- e& ?0 `/ `
Compressed length: ".strlen(gzcompress(,));
% @" S( R/ N  g% x; a0 r& W: [% s2 E.= ;
  {+ ~- A0 D. D) a1 E* |} " m7 o& e) }" q
header("Content-Encoding: "); 6 |- R% `- E1 R: N3 E7 g5 o4 ]
print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; 0 d2 b6 Q5 [" s8 R* z  V
= strlen(); 1 U) F$ w' ?( j3 |+ ]3 b4 s
= crc32(); ( q; t8 `' f( p' [
= gzcompress(,);
  [/ r7 K) v/ z= substr(, 0, strlen() - 4); 8 m; C  h$ H( y/ r7 ^
print ;
. @+ y  w" S5 k+ y& r4 \0 Oprint pack('V',);
% P7 r- h9 T3 nprint pack('V',);
8 i5 v* X) c* T2 l- _exit;
/ S0 L+ Y  T+ M9 s% ^& O0 \}else{
, z6 ~7 Z4 F: x& e! iob_end_flush();
# y; z( ^+ M1 l+ r7 R" iexit;   a6 ]0 ~& }# f- {
} 6 J. T: j7 W1 m7 C3 x
}
6 h' C- X. x  z- }. e$ O7 L$ T?>
7 {( l. T" D, U2 }& s5 y, o-------------------------------------------------------------------------------------
4 c! d5 d  F. E- a---------------------------------
5 i! b% Y8 [3 S& d& S$ `这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 ; u- p: n3 w* w1 w; l5 R* H* k
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……
" B9 c* j( w/ O0 Q
! `+ n; X* i8 Y5 L, U+ i参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html




也是支持,我代表大家顶你了  M' C) D: I; u; |6 y
, o( {7 w$ C/ z: d, A! U" q2 K7 Z! a0 J
. K$ \/ F: }! Q
7 C& n# x# X% n

1 G; V& l8 @& }1 P5 @5 F# J$ g$ g, I* Q" p' t6 o

; L1 S- d* I# b8 s* D" v; y+ r' y, g) ~4 ?, d! Q2 l$ X+ Y

2 `; `8 ^7 o- a0 W1 d
5 w2 p$ s4 h; G4 h* J- w: Y
* q3 Z- V% ]  z' T5 u  b3 D/ i* A9 w" |% o! u4 ^( O. i
! `; u+ ~8 s$ ~4 P
maiwenping.org


TOP

返回列表
Namecheap
Namecheap.com - Cheap domain name registration, renewal and transfers - Free SSL Certificates - Web Hosting
互联网安全