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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑
' J7 e. R3 C# c+ ^  T
: Y3 ~9 a1 ?  o( N& j" R3 i我们先举一个简单的例子,让大家对Output Control有一个大致的印象: 6 t6 f" \1 z- v' R8 d
Example 1.
( m% O0 d: ^8 ?; p3 q---------------------------- 3 S' I2 b- m$ ]5 y/ X! o
----------------------------
& F& }7 T- A5 K9 @; Z: A1 fob_start(); //打开缓冲区 ; H! q& s' I. m9 K9 b& m
echo "Hello\n"; //输出
4 _( @9 {$ a, g, ^4 iheader(“location:index.php”); //把浏览器重定向到index.php
' `0 z3 C, |; ^9 n6 sob_end_flush();//输出全部内容到浏览器 7 q3 B' g. A0 s6 \5 z2 ^
?>
/ U7 Z1 P3 U1 w) U( I7 T# e-----------------------
( ]; @  I! u5 e. L' I- ]! u----------------------- 2 ?4 l( H) @, N+ o4 c* ^+ p9 y. x# h4 \
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用
) s+ k. \, t4 L  W- I+ S4 v这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 9 O3 J7 T6 }7 W' f% K; j' z) _
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had
! s, F1 M; N: t9 i% f7 `, _8 w4 Call ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误! 8 X+ u. ]+ R" }9 B% }1 Y; a
0 ~2 l6 L' v7 S2 d2 R9 F2 r, j% F- A" _
一、 相关函数简介: ( F! w8 R" q) ^3 u8 v. c
1、Flush:刷新缓冲区的内容,输出。 4 ]* m: F; K! ?8 V
函数格式:flush() ; A+ M- B- s7 @+ q  E
说明:这个函数经常使用,效率很高。
. h+ ]- z* e6 l( R9 o2、ob_start :打开输出缓冲区
( Q/ C; U7 m" F6 u" y函数格式:void ob_start(void) 1 d3 M2 O' ?4 x7 C6 f6 E$ ^, o
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。 . ]) Y$ r4 _/ O6 U4 X
为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。 0 g, w7 ?. D6 o7 X
3 、ob_get_contents :返回内部缓冲区的内容。
, e- ]- w4 K5 ^6 y使用方法:string ob_get_contents(void)
7 A3 V- t( E" e/ `2 k6 h说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
2 L$ }+ A% h% P4、ob_get_length:返回内部缓冲区的长度。
6 L* ~4 h. U8 Z: O6 |使用方法:int ob_get_length(void)
7 {$ N# O$ J, m/ Q说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
- _% T' e, K7 ]3 q活。则返回 FALSE。 ' v0 @$ J0 k5 f+ ?3 X2 O
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
; S% D1 u! p: y3 }使用方法:void ob_end_flush(void) 3 f. e: J0 F+ m5 j2 g
说明:这个函数发送输出缓冲区的内容(如果有的话)。
% U, T2 y0 ?+ G+ P- h& ?( K/ d+ m: R6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
5 G+ f; ?0 x( E# _/ E7 q使用方法:void ob_end_clean(void)
. ~$ O8 f0 P" Y* P0 d0 p- u说明:这个函数不会输出内部缓冲区的内容而是把它删除!
  J3 g% m: s6 b3 _0 r' G9 w. U7、ob_implicit_flush:打开或关闭绝对刷新
! Z/ D. T4 x% J* w8 P3 f, I使用方法:void ob_implicit_flush ([int flag])
" j& d1 J; W# S说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而
  n( N) H, A1 Y: x$ Vob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
  k. v1 c! ~: R# B# O" q8 @3 r接发送到浏览器,不再需要调用 flush() ( I8 N" |2 C* b( J" V4 s5 y
2 H, ^" A3 x. S
二、深入了解: ! R+ G! |- ~. l, m# j
1. 关于Flush函数:
9 L9 i7 S) C5 x* Z/ ~5 l, A这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
. X# D% ~) N" ^$ c2 d" R) [6 O的cache.我们举一个运行效果非常明显的例子来说明flush. + R. L% G: Z' V
Example 2.
5 c% O6 P* L5 k" G/ r% D---------------------------------
8 F& M8 h: M4 @& C--------------------------------- . G# y) C7 Q8 y* |" ]) K1 h1 l) X
for( = 1; <= 300; ++ ) print(“ “);
7 H) n+ k& C5 z8 B0 @& |// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
" c( a8 Y# ^( P$ ?( ~- y) U) X1 W// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
+ P# J  Y: D5 c2 j/ i6 G// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会 . g8 v1 i5 E$ e( D# F8 m
// 源源不断的被发送出去。 / R- V6 c6 ?8 |+ x" J3 W
For( = 1; <= 20; ++) {
7 f! p0 v0 C" T. }3 _9 Mecho .” 4 X# E1 Q- Y8 Y
”; 1 a1 a1 P/ \% B% t- f+ P5 {0 b
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
: j+ S: P* X. Y+ c4 Z1 ysleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚 / C/ \" k% v, }  Q- H* i
}
) _& ?5 e7 j; I/ w) L  m?> . M) e1 L. I% m  h5 z
---------------------------------
& r6 @1 A! F/ O& B* g--------------------------------- % v- e9 ?) k  S# i5 p1 c( \
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
% j! B# T6 [) f6 S& oPHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L " T1 I6 c4 a! H% N2 J# F8 m! y
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush 5 W4 t) U# ?# Q
(),这样做的好处是:提高效率! / i# r! U8 P: [3 D( y$ {9 }" K
2. 关于ob系列函数: 0 P3 k% r  [: c! i( ]" O
我想先引用我的好朋友y10k的一个例子:
1 P! {$ @; R8 ^; [) @  g1 QExample 3.
* ?8 [, T$ \2 H, K---------------------------------
4 R" i! u& a% {; i+ \5 A; w---------------------------------
5 {* j5 z! ?+ [  n& k2 M比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
  O" y- d) z: e5 c保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 - n# T% E  p5 p. @. n
缓冲区的控制,我们可以轻松的解决: 6 B4 O; D# K9 S5 A
---------------------------- , n6 S) R* X# D9 ^! O
ob_start(); //打开缓冲区
! L1 H+ l" c/ N! w2 y0 m0 o! Yphpinfo(); //使用phpinfo函数 $ }* L# W) h  N9 C$ C
=ob_get_contents(); //得到缓冲区的内容并且赋值给 * A* r3 c5 p8 `$ F8 g! ~- n
=fopen('info.txt','w'); //打开文件info.txt ! b. n. n! G9 H
fwrite(,); //写入信息到info.txt
0 Q* {' n0 V* vfclose(); //关闭文件info.txt + D4 a& p4 c8 ^0 @% ?" K
?> 9 C0 a6 e6 F' u7 W
------------------------- 5 g4 o" m) V* ^+ E
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上
$ n- ~. b6 |5 ]4 f/ K# B3 i# X面就是将一些“过程”转化为“函数”的方法!
+ V  D5 }1 N0 M
, y2 y! h, u9 @8 \7 }或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语
3 z5 W! o5 ~1 {& w法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次 % ]4 D: {/ E5 S5 a+ W/ G- [
调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
2 k7 Z/ g+ h6 ?& }9 N- b了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/  `2 u  Z% r& c$ M) B
------------------------------- + B; W$ T& t7 @) X7 `" D# ~
-------------------------------
1 M5 {4 K: c4 ?( i3 v; f可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌
4 h6 Y6 i) j8 E( o握了使用ob_start()的要点。
" M' \9 _; P6 Q' j+ U" d2 y<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
$ ^4 x- z# B  B/ b! |(),ob_end_flush()(或程序执行完毕)之前不会被输出。 ' ~& ~4 a$ Z% r( [
<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及
* d0 j& b* b% B8 wsession,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后 # p  ~' ^( b; W0 i# u$ ~
自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得 ( y% ^9 n6 l0 |6 h, L
到cache中的内容,然后再进行处理…… ( Y, a) U: z. w5 b9 u6 G
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 8 J) M  z# N) {4 Y" S- B* W$ m
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。
5 c' a3 h$ x' v4 A来,让我们看看能用ob系列函数做些什么……
0 F8 n( ^' \- `5 f一、 静态模版技术 / ^( j9 C' P) A, [
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页
. I5 H' _- b  h5 ~面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用   m2 ^/ ], C7 Q# Q! u, j6 L
PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带
4 v3 J( u1 V  A$ S1 j. P来的好处是非常巨大的。
. ]1 y1 F- f0 f5 @) k  T' N我所知道的实现静态输出的有两种办法: $ K! d8 W/ c6 D
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
3 S. v( u/ ^9 H: U* i2 r<2>.使用ob系列函数实现。
5 M( _9 o: Q4 t* W) C7 @+ \- M对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。 4 p, m8 w4 `$ w
我们现在来看一看第二种方法的具体实现:
+ j. ^+ h; V  u1 p, zExample 4. 6 u! t' L  F& \$ F( z
---------------------------------
" z4 {5 @/ ?, u$ A--------------------------------- ! Q6 |6 J( [) A) Q! ^  Z% j6 @! @
ob_start();//打开缓冲区
$ a: P" d9 B% U/ Z?>
( p+ b& Y: k' o. N: pphp页面的全部输出 2 r4 g' B- F8 e6 ~7 [: A
= ob_get_contents();//取得php页面输出的全部内容
( ?+ Z5 F0 \( m  U: k" W  [= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
. p' E# A( [' }fwrite(, ); //把php页面的内容全部写入output00001.html,然后……
% T3 U$ v& A9 Ofclose();
) t5 h: ?4 V/ X4 W1 w. ~2 b2 m?> " l7 ^) z% r& W9 P
---------------------------------
4 T3 |& @' u: G. R; W--------------------------------- 2 G1 q% G# j+ Y1 t. a
这样,所谓的静态模版就很容易的被实现了……
% j3 h4 Q8 s9 d2 H, Q* l  D( C二、 捕捉输出 + G$ n, y6 F! E: f6 D4 }
以上的Example 4.是一种最简单的情况,你还可以在写入前对
. G- L. D; k4 V$ o" A" t! h你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。
4 c; x6 a, W. E; O* w# n* Q个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的 + `, \  q+ J4 U( l( c: v# a0 V# O
想象力……
" Y- M: {- r; A- P% mExample 5. 2 f6 X/ `# U/ W, b- J4 \- |$ b1 g
--------------------------------- ; Z4 w6 |' \6 n, K; z
---------------------------------
% ~5 H" o8 W7 |9 U/ Q: zFunction run_code() { ( ]# S' ?: B6 N4 A! L! d9 Z/ m5 h; j3 I
If() { 8 U- L% T' G& P4 U5 c
ob_start();
/ k, L# L# v6 D6 W  N" xeval(); + ?  r2 M5 W) S( o/ e; M% u
= ob_get_contents(); 5 \0 O* c  D) F
ob_end_clean();
/ i2 c' T; E- U; V! C$ i; x}else { 8 A" C" p: ^1 }# {) I9 ~0 ]* r
echo “错误!没有输出”;
. d" W9 x1 O+ ^& n% A# {exit();
  ^5 h5 Q  N2 L1 a( Y} : F" Y" c' B6 w  f1 _
return ;
! n& V9 `0 D; M4 s" E6 n} 7 v" A; ^- r9 F. j/ L
-------------------------------- + W& h% p- u2 a: y
---------------------------------
# v9 T+ Y# B+ f以上这个例子的用途不是很大,不过很典型 3 t) r( b3 g% _& p5 Z
子用eval把
  V- u) @  q9 r3 `* V' B, i; V. _Example 6. 加快传输
4 f) H7 ?) j$ ?---------------------------------
- d8 n) B' Y& z2 h  m# I5 A- K---------------------------------
5 e. d/ ?) @  `, f; ~2 Z. b5 {" [/* 0 V; T4 V/ @2 U7 w# H/ d
** Title.........: PHP4 HTTP Compression Speeds up the Web 5 K/ |* t- n, ]$ j* R7 F2 A
** Version.......: 1.20 1 U$ Q8 r6 q, P3 k9 o# Z4 [
** Author........: catoc 7 A' T! w0 n% O
** Filename......: gzdoc.php # z7 C" e9 `9 ]6 a7 b+ O
** Last changed..: 18/10/2000 4 Q* q( b* O5 v9 A
** Requirments...: PHP4 >= 4.0.1
; c- w+ c0 }& s6 Y  n2 T** PHP was configured with --with-zlib[=DIR] # c: j" O. h/ |( D! y
** Notes.........: Dynamic Content Acceleration compresses
& W) f) I1 n# O1 F  t# u% [( A: X** the data transmission data on the fly
" j$ e; ^& j# C0 p: B3 K** code by sun jin hu (catoc) 3 s* V! O6 g$ R& u
** Most newer browsers since 1998/1999 have
& y) \7 s4 K) `** been equipped to support the HTTP 1.1 , u9 l! S) Y% g; ~, E5 T/ R
** standard known as "content-encoding."
& g% U* d6 z+ r9 K" O3 @9 }6 G** Essentially the browser indicates to the
( S6 I, H( m) U5 F** server that it can accept "content encoding"
) O8 G. I& J1 Q- L** and if the server is capable it will then
0 s1 W4 b9 H" @: L6 g** compress the data and transmit it. The ( I2 G6 ^6 E, ^' D" Y
** browser decompresses it and then renders
' \6 a; `4 N+ ?1 T** the page. , c+ s3 K& x  Z; D; O: x
**
9 @- n+ s: \$ x( y** Modified by John Lim (jlim@natsoft.com.my)
2 s- j2 L4 z8 b! ^# C6 r** based on ideas by Sandy McArthur, Jr & x: |  s# I, b/ a- }  y9 ?. K- ^$ K
** Usage........:
4 i, ^8 m7 I' R! `3 q9 G** No space before the beginning of the first ' ** ------------Start of file--------- ; e- K: r  a2 ?  t+ I3 D0 N* H& O
- : j8 V# f: ?: Y. \1 g
** │ ** │ include('gzdoc.php');
9 B% b; B- U- C0 H8 m5 Z' H** │? >
( h* L) T4 i5 P* n( A** │
' K/ J6 i2 [2 ]- l** │... the page ... ! T* V2 H8 V4 Y( T6 {
** │
7 b3 O* N4 L- p" P: z- `8 x* Y** │ ** │ gzdocout(); * s; w' H. `( R9 W
** │? > $ K% n8 k3 C/ o6 l
** -------------End of file-----------
7 ?* y4 Y( ^" t* O  S' o*/ ' J3 l& B1 N& ?4 ?: T6 o
ob_start(); - q; j( A5 x4 B, ^: L
ob_implicit_flush(0);
, O8 O, m# _5 W) S  |& M6 F$ Qfunction CheckCanGzip(){
/ z5 R, _' E) J$ P, Yglobal ;
8 o& M4 w: F: h6 _7 ?5 u; ]if (headers_sent() ││ connection_timeout() ││ connection_aborted()){ & m* d2 d8 B: A. a
return 0; 2 m  a3 P. x0 ]) ~* ^8 G% Z
}
* Y- N4 Y7 k8 ?0 r- B8 fif (strpos(, 'x-gzip') !== false) return "x-gzip"; * K0 C0 p0 C$ d6 c/ x% M
if (strpos(,'gzip') !== false) return "gzip";
. D# ^5 Z- C4 i1 D0 K! Ureturn 0; . I5 h7 s1 ^- L- r9 f4 j% b6 @: I
} 5 c8 z. d6 w, m2 @
/* = compression level 0-9, 0=none, 9=max */
+ u& J2 U; f0 O2 m9 p* u2 t; Afunction GzDocOut(=1,=0){ ; e2 a2 y) L3 p! I) ]/ G
= CheckCanGzip(); 3 Q" s' K0 T' x/ x: }, p! Y& M) H
if (){
2 d! R1 n7 d9 q  A( a! Iprint "\n\n";
9 H) l& @' h$ v3 e5 n= ob_get_contents(); 4 m; @3 F# u! H0 y
ob_end_clean(); - G9 ~" r% E2 m9 [% }
if (){ 2 Z0 e& U3 ?( B  w, m
= " 5 }2 u8 C" t2 h2 ]
Not compress length: ".strlen();
# p7 A- q$ y/ \6 C0 P.= " 0 U  X- Y5 d& u9 }; T+ m5 U8 U  s
Compressed length: ".strlen(gzcompress(,)); 4 c) g7 V% |6 e3 V$ O
.= ; ! C6 p! z. ~" c5 c
}
7 Q- x/ }- b# p5 q" L& s4 k3 s) pheader("Content-Encoding: ");
. B- \4 h; |( Eprint "\x1f\x8b\x08\x00\x00\x00\x00\x00"; & ?4 C% p1 F+ z
= strlen();
# B& k9 m' J! C+ t5 @9 F. H; f& ^= crc32();
) e# G5 h5 i$ d= gzcompress(,); 7 ?, N: c# ~1 s$ V0 x+ F% M
= substr(, 0, strlen() - 4); ! Y3 m2 \% N2 w, w; o- {- s7 H- R
print ; 0 `* ?) W8 N0 ]$ O  h1 {
print pack('V',); 3 N9 m" ?6 Q' R
print pack('V',);
9 r- T. C( l8 gexit; ! w+ ~) U9 [) m5 w3 o
}else{
9 q/ R; W+ F4 O7 |" E0 Qob_end_flush();
3 o$ D5 B9 |' ~; e: Qexit; , d& [! V3 d6 X0 V1 C
}
( P! {4 g- O& R% @& h# E  d2 g} " c- Q+ p% y7 d& v
?>
0 g3 F5 G* ?/ {4 s-------------------------------------------------------------------------------------
/ a, S2 Z# E+ r  ?; u, D/ w--------------------------------- & D) Q4 D* s: j5 S
这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 8 C4 H) ~+ P0 X' c
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……1 p4 G' l) c. ]
5 a  y. J* U* H; A/ o! L
参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html




也是支持,我代表大家顶你了7 f5 T3 s! w3 ]1 U- L

) n: ^% Q! I- S# ^6 B0 C
* Q$ ]7 _/ h) z% b( b2 m) h) ]( r( n8 e% I. m' a
8 g  v  ~) r, ?2 t9 p/ c! m5 l

/ k% C; l" T' ?  X6 b/ _6 E: @! S8 R( K- G7 a4 R( N3 L

  _  d* m% U# o9 `5 y$ z
& w& g; _) k% p- X" r! K7 R+ D( f" M' Z

. ^# e# N& ?/ d- m3 A% n9 H+ B8 U

9 h1 z( [7 ~! v+ ?7 K- N( omaiwenping.org

TOP

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