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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑 ( Q5 ^2 R( l* l  b$ v
% y8 i+ E: e$ I" [2 K) o
我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
$ ]6 U1 }. X% N0 Q% ?) CExample 1.
3 H/ r$ I& l: O---------------------------- 4 O- J/ M. ]! T) k6 c  W
----------------------------
. A4 L* T  J/ I0 v/ u* Sob_start(); //打开缓冲区
& t. r4 U4 W: ^1 R+ qecho "Hello\n"; //输出 2 W2 g6 G4 `- N  i7 D
header(“location:index.php”); //把浏览器重定向到index.php % {( r" B$ h' R) a, Q
ob_end_flush();//输出全部内容到浏览器
$ E3 y2 ~7 w8 j- D9 C?>
  m9 s' Z8 {& j0 a% o% V-----------------------
5 _2 w2 |6 y1 M) S5 |-----------------------
& S! J- n  }3 a所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 9 G: E$ o* _/ Y9 [/ J4 ^% `
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 ; b, j+ o5 c; ^3 i. N. Q
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had " U+ s3 P2 v* ]1 w* |, S& l3 r" z
all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
" l! m4 [) G+ N; C: z6 f4 i2 r5 b9 {  u0 b& `% D- n6 B) d; g
一、 相关函数简介:
3 r# ^5 z2 B* ]7 U- E1、Flush:刷新缓冲区的内容,输出。
: N6 `( @' ?0 V% C! y$ G. b7 E' m函数格式:flush()
: d9 P) ?* L# o! e说明:这个函数经常使用,效率很高。
. x" [$ d7 z3 A: s2、ob_start :打开输出缓冲区
3 G: h  b$ y2 f: _$ _& c3 N4 W函数格式:void ob_start(void) 3 f) o. r3 c# a
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
* ^) h1 ^4 _8 x) K3 K" N为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
/ a. n8 F0 C2 m2 z- j! c; C% J% f' |3 、ob_get_contents :返回内部缓冲区的内容。 % _' E$ S4 d( ^' X" ^. r5 I
使用方法:string ob_get_contents(void)
, C+ @+ z9 Y* f* N' S+ u, i说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
: M0 d3 E( |6 P; Y' M4、ob_get_length:返回内部缓冲区的长度。
* X: U" P/ [7 h7 W6 G  S使用方法:int ob_get_length(void) % o5 l8 ^9 V; i
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
& {1 Z8 ]. T6 }  A3 B5 S活。则返回 FALSE。 + E  ~: L6 W* S- B- f
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
4 [& m: ]! i0 Z- h  B6 B+ Y! d. e7 S使用方法:void ob_end_flush(void)
  g* Y( C/ }. |3 t6 l说明:这个函数发送输出缓冲区的内容(如果有的话)。
7 J2 H3 F- P0 E. C2 l6 o6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区   N7 x) d% z+ y4 g5 Y; a
使用方法:void ob_end_clean(void) 7 |; p$ A, Y# p3 C, Q2 |+ _
说明:这个函数不会输出内部缓冲区的内容而是把它删除! $ C$ i4 ~4 k+ p
7、ob_implicit_flush:打开或关闭绝对刷新
& t* d3 ~7 \0 q+ @: y% ~. K2 R使用方法:void ob_implicit_flush ([int flag])
) K9 R& W- a  L1 |/ A说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而
5 x, T1 X: r0 v! U2 ?+ R5 wob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
* w: K5 }  J& B) a. t8 k! o% C接发送到浏览器,不再需要调用 flush()
0 E8 w) i8 m* U
4 j. j& c* x! f6 T: ?, Z1 r二、深入了解:
) F4 o. m2 m7 u1. 关于Flush函数:
1 B9 V2 f- R7 v3 \; C这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
& Q4 K0 w; U3 m的cache.我们举一个运行效果非常明显的例子来说明flush.
5 O! g, v9 O0 j& {( KExample 2.
+ P3 v4 p: g8 Y1 a3 ?# t+ d& M3 }--------------------------------- , f. @; j+ I) e- v) g/ Q
--------------------------------- 0 F. c) O6 w' s* u9 [# r, T5 u9 M( q
for( = 1; <= 300; ++ ) print(“ “);
! q! y7 p) D0 S+ `# P4 T$ r+ v// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 & o2 F3 d9 m% `( c4 n( G$ f- C2 U- z
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
! y! d1 |2 M" o7 a) N/ Q// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会 5 u9 B$ E. O$ l" K& E# X3 l4 I
// 源源不断的被发送出去。 : c2 B. Y% c5 t2 z# Q$ r" G4 |2 `! U
For( = 1; <= 20; ++) {
, c' n$ G6 A$ q1 ]- `echo .”
2 c  h+ D$ `3 S1 e* ?”;
9 \' m: W4 r2 n; F/ \flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上 0 ^9 Z- N3 M2 |: y9 a+ E
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚
" ~- r4 U# \, i}
; q3 I4 E% K' z  Q8 I) {! K5 f?> ) F9 v7 g: Y* w; j6 H3 W
--------------------------------- 6 I/ r: l* f; T0 N' i- t( Z
---------------------------------
# x$ a% S+ \1 p" E# ]. ^- ?具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php ) m7 Z3 c; W. _, p
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L , D0 e' ]  ]8 z) y3 J
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush
0 ], m# J8 E. q. j(),这样做的好处是:提高效率! ) Z; ~- j& k* R2 y  t
2. 关于ob系列函数:
, t% O; ?# T0 A: N/ V我想先引用我的好朋友y10k的一个例子:
8 U/ o/ @5 @2 j! R$ \Example 3.
: E% ^& f( A5 u' f. o---------------------------------
6 ^% G5 I  Y. ]" V/ F3 L6 z---------------------------------
6 c! U  n% s3 ?7 `* s! ^8 p, C) ?2 ]比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
  o0 K7 ]0 o$ `0 W保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了
! i# Y9 l9 n& k& ]7 b- z缓冲区的控制,我们可以轻松的解决:
5 D& w$ \2 M3 S7 v) z1 L+ `- p----------------------------
  `8 R% I/ U$ t. Gob_start(); //打开缓冲区
+ _+ |. k2 Q4 V, r/ {* vphpinfo(); //使用phpinfo函数 / h0 z- w! C8 X5 T1 U: t
=ob_get_contents(); //得到缓冲区的内容并且赋值给 0 L1 L  v# f) h+ c
=fopen('info.txt','w'); //打开文件info.txt 7 D' {3 j! y1 X* T) U" c
fwrite(,); //写入信息到info.txt
: P1 M* B, T$ j# l  n/ @+ T+ F  Wfclose(); //关闭文件info.txt , T4 ~7 b/ V* Z3 N! [, D' m
?> " r6 B* q# Y' z7 F  e2 j7 \
-------------------------
  Q# }" N8 R4 q1 ]用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上 3 j3 M- p5 _# r* e( E1 k
面就是将一些“过程”转化为“函数”的方法! 5 q9 Z0 _# \, u/ o- O' J8 H, l

+ L) V( S2 ^4 @; Q9 z0 u( p* [或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语 4 j# a" k# c: q" _' X! L: L7 V: l
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
* F! F+ e+ S( Q. C/ `# [: j7 }; x调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留 3 a1 ]" q+ Q* I1 L4 c9 S
了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/3 L6 V# L6 I8 M' ^
-------------------------------
5 s) c9 ?' w7 p+ o1 `-------------------------------
/ M. Y- i7 a# [6 K4 X$ Z% G可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌 - u8 U* d4 x- @" t( Z2 C
握了使用ob_start()的要点。 ' l; l# M: j$ ]
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush ) R7 P+ U$ h3 B8 G6 I: o# ~
(),ob_end_flush()(或程序执行完毕)之前不会被输出。 7 X- b: S( |; f  K. n  a
<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 - |  Q" n& D% r" X" P9 p
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后
& Z9 x3 j; h* T  }4 m9 T自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得 / W( V, }/ c' l+ r$ C
到cache中的内容,然后再进行处理…… + m! b, w% K  J6 a: @7 T
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 4 |) G1 H; F& b1 {2 X( ^4 K  J5 }( }( x
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。
2 {" ^, A  m9 \" r% r% e& B来,让我们看看能用ob系列函数做些什么…… # {5 v% [; w# V9 J3 h6 z
一、 静态模版技术
; O& S8 y* Z8 e0 z; ~3 g  F0 P. Y简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页 3 Z& @- G0 r# V
面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用
1 R) }% P9 ~! i  [4 n; gPHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 + l3 O6 a% Q" B( y4 w6 k6 @' P
来的好处是非常巨大的。 3 q2 {* H! j+ R1 {# l
我所知道的实现静态输出的有两种办法: ( m$ P+ ^: s) u& y, X# J
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。 % H- ~1 q4 x4 |3 J/ J# z& ^
<2>.使用ob系列函数实现。
7 S- ?" @7 K3 q: V) a( S对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
, m+ e! [$ |( ~& c' l& o4 D& I我们现在来看一看第二种方法的具体实现: ! `$ l: q2 N+ S/ M# q% H4 S
Example 4. / f/ ^; K/ j8 C8 j
--------------------------------- ; x) w" P$ X2 X# ~
---------------------------------
8 s7 M. \3 @, X2 ?8 j) _ob_start();//打开缓冲区 6 l  ~. N1 d- y" c
?>
4 X7 D% q6 P, e$ ]php页面的全部输出
$ U. I2 o1 c( N9 n5 K= ob_get_contents();//取得php页面输出的全部内容 , H9 l; E5 I' a& S; \
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
' z, B8 |) O% f7 p5 H. Xfwrite(, ); //把php页面的内容全部写入output00001.html,然后…… ( [, p& J* N2 o. q8 i& a! u
fclose();
" x) s5 L' Z8 n4 r) }9 Y?> * ^9 x* N% N# N, A- H% f4 j
---------------------------------
( v9 W. k; G  J5 n* ?--------------------------------- - i& @1 g5 [1 r- N' h7 C
这样,所谓的静态模版就很容易的被实现了……
9 S7 ~9 V5 f) Q8 b2 E. q( I二、 捕捉输出
* d+ g$ w8 \7 h  l5 ?以上的Example 4.是一种最简单的情况,你还可以在写入前对 5 _% u5 d& V3 |# u+ y- G6 Z
你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 . f* O9 N5 g7 z3 [+ W6 P, A3 b
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
: M0 q7 V) I% c( ?# l想象力…… $ E) M! [2 i+ i8 R! b6 U3 n6 S% n: u
Example 5.
% e% R" {4 H5 i$ j/ K! N+ d  B--------------------------------- " h# I' c( [4 |) g
---------------------------------
6 S$ B( Y: V2 X, d) bFunction run_code() {
# t  ?! B; m' [6 aIf() {
* w& Q8 ~. E( h+ f# G3 C' iob_start(); , U5 i) e, ~9 g
eval();
6 H% P9 v) V, H1 W8 J= ob_get_contents(); ) I6 S8 ?8 I  c0 y  U( f5 w% {( z& H$ }
ob_end_clean(); 1 @4 {1 W/ F- r
}else { 3 Y, K4 U1 o# ]; p0 ~( f
echo “错误!没有输出”; $ k+ r/ V+ z- U7 B
exit();
- V9 E4 |: [6 X' j$ w} % e. f/ P0 R0 I4 g( ?- {6 M* r: S
return ;
7 Y: P. T! h' a* p} ( Q) F: E2 M- U. R. \; B
--------------------------------
0 C# P5 O7 q1 O  T' D" d---------------------------------
; R& R6 Z1 s! @' q% A以上这个例子的用途不是很大,不过很典型 ) ?$ l1 W' i; i: t( }/ f; E, @
子用eval把 4 x3 V$ @% D# _0 `
Example 6. 加快传输 & |" n/ R; y$ \
---------------------------------
9 V$ u9 g; B# F2 M3 x, i; z---------------------------------
5 f# A/ e' A$ n. }/* ( Q, x6 r) b' Q, n
** Title.........: PHP4 HTTP Compression Speeds up the Web
! L9 B2 B: ?1 x** Version.......: 1.20
, v, f1 [7 l3 s& ^* g  z7 f** Author........: catoc
+ V9 o' i" _% Z0 L7 X** Filename......: gzdoc.php
& }* Y- r9 t1 k7 c" {* P$ K' h** Last changed..: 18/10/2000 * g" P9 C( A# s
** Requirments...: PHP4 >= 4.0.1   N4 n5 J! G1 T3 {4 V! b
** PHP was configured with --with-zlib[=DIR] + e" b5 }) c7 F
** Notes.........: Dynamic Content Acceleration compresses
% Z- n6 g# m8 L" s2 W** the data transmission data on the fly
: d2 n  x- x0 N1 p) ?** code by sun jin hu (catoc)
$ O0 N& `$ z0 s3 r: X# F9 A** Most newer browsers since 1998/1999 have
5 U, u* G( r, F6 h" x, }1 x** been equipped to support the HTTP 1.1
! `: [4 _0 A0 w! x3 a/ D** standard known as "content-encoding."
2 c* {' R5 k0 U' H% }8 `** Essentially the browser indicates to the 4 Y) A. L& a0 g' [0 e2 M/ z
** server that it can accept "content encoding"
6 ~, C- ?; ?7 B** and if the server is capable it will then . d/ L& z: E6 E  V& n( V2 a
** compress the data and transmit it. The
, [0 d# P8 v5 M/ G$ Y$ ]) `* H** browser decompresses it and then renders
  K6 s3 q0 l3 Y** the page. 0 D& I3 X, {$ K: I4 Z9 I  a& f& r( J
**
* A5 P! ]; s7 T/ B** Modified by John Lim (jlim@natsoft.com.my)
4 c$ p; {5 v6 @# f' |; Q0 S** based on ideas by Sandy McArthur, Jr + c5 Z3 H. y8 O3 r
** Usage........: 4 O, q( E/ q. X/ K: d
** No space before the beginning of the first ' ** ------------Start of file---------
3 Y/ y0 \8 I+ y8 Q-
8 x% Z% s5 Y6 h, N7 z9 a3 s6 `** │ ** │ include('gzdoc.php');
7 H) t5 x! ]$ K4 T# n** │? > - D+ z0 ?- i; X+ |9 s' \' n) v/ _
** │ 6 O7 Y9 |4 D3 O, T# K  l
** │... the page ...
/ R) F/ [# ^. s% b** │ ; a7 N* W- i  ]
** │ ** │ gzdocout();
1 Z( `( E& k% a4 ~3 [8 g; N** │? >
( H! {1 l) A" a( D** -------------End of file-----------
, O& N% g* R) `2 d! \- f*/ 3 g2 x' ^& N  C: D9 @0 ]
ob_start(); # `9 f5 k  D* ?& F8 b2 ^1 V$ R9 D6 U5 h
ob_implicit_flush(0); - X  x' D3 B8 C1 c) J( Q
function CheckCanGzip(){
* y; J5 A, m$ z8 aglobal ;
- J9 E5 c# M( Tif (headers_sent() ││ connection_timeout() ││ connection_aborted()){ $ H$ L; Q( ?$ Y. S2 G$ E5 d* L
return 0;
- R2 x( I6 j# V8 B8 b- ^  w. ^9 v} 9 `* p8 ~1 [6 T* e7 l* B3 e/ k9 I
if (strpos(, 'x-gzip') !== false) return "x-gzip";
& h+ r$ l& W4 y/ o" gif (strpos(,'gzip') !== false) return "gzip";
+ U% Y% R7 O4 k$ G5 n9 u, r% [" |return 0; % i) W2 Y5 P" q
}
; W. M6 Y2 r9 x4 j/* = compression level 0-9, 0=none, 9=max */ 4 i+ L9 s6 F+ p* L* e9 ]& d( M7 e
function GzDocOut(=1,=0){ 4 A2 I. [( d5 C# ?/ }9 Y  h( W
= CheckCanGzip(); ; b$ N2 D, x" B9 r* j0 H
if (){ + b9 H" C* M! F2 `6 A
print "\n\n"; 2 c' O9 n0 w  j5 N5 D: ]3 Y0 ~. J+ E  S
= ob_get_contents(); / r* U: e/ n3 h$ @2 i7 P
ob_end_clean();
! K# B3 ]6 @! v( |9 j; Rif (){
. Q& H; v0 y2 Z= " 0 G4 \. x+ m& z
Not compress length: ".strlen(); ) |/ R, u/ T% ^2 n2 ?! M2 n
.= " 9 d6 ~; _) ?% m+ \% G7 ~: ?
Compressed length: ".strlen(gzcompress(,)); & ?* U5 j- e  f  f  Q) i. Q
.= ;
" c; m/ n- m" _; y" ~! ]}
( j% Q: G3 d/ Dheader("Content-Encoding: "); * b0 M8 j- C' M- j. O( y
print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; . o' g$ }: U( Q9 p
= strlen(); 1 p+ H+ R& c# O0 }3 J# Z8 H
= crc32(); 0 {/ b7 K+ f! U% L
= gzcompress(,); : w. N, }/ i! z, {  r( I) ?
= substr(, 0, strlen() - 4);   a2 ?- `+ o# h9 e9 [
print ;
2 q5 f, j, E$ eprint pack('V',); # K6 G' o, S; k
print pack('V',);
( W* V0 E/ S. }. o3 hexit;
, o7 C7 p7 r8 M6 u, v}else{ 8 {! ?' L* b5 P6 m) h
ob_end_flush(); 2 S& }7 x: {, r4 z5 H
exit;
# \8 i2 w& |1 E1 ?$ X' p. h- @9 c}
3 \# I( Y! N9 Z5 N9 _# O}
- I6 s+ D1 S7 i' x' k! X?> 1 }  `9 s4 f$ @! K' f6 q5 X$ i
------------------------------------------------------------------------------------- 1 x% O9 [0 ~& n; g* L# H
---------------------------------
5 q/ ~' [& T( R+ R, d这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 ( t  Q  e, s! ^& t. q' |
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……, [3 f9 _! [2 h8 q8 w+ v9 m

0 M0 z* M5 w5 l. t  I: O  C参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html


也是支持,我代表大家顶你了
( {. X3 R+ F) p. U/ V- i" F/ d) ]+ W+ L; @  ^1 U
" C8 T) b6 [* `

8 h; a1 G  l+ E4 [. h2 b: ~9 B6 D0 k7 v; [& R

2 \! W2 n+ ^: d! [1 x- A5 d5 g( r: C/ T; F  }+ _

8 H7 g0 C8 i7 V
7 i0 x# r5 S" R. {
" s9 T/ W, K" M8 ?$ c1 w# Q6 H( M
6 v3 `$ o  h' V7 G8 n5 o; l5 j) e2 a# Z+ H; m6 @3 w( @% t: ?
% f4 b* g! o* n% x
maiwenping.org

TOP

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