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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑 5 y! G& Z9 A1 R) l2 x

1 j. v* U& P) W- r& p; e# V0 D我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
7 G0 Z# {  N6 r. U+ aExample 1.
3 W# C: N/ D% ]5 {! U----------------------------
; D- P! N9 P- v0 z& w" U---------------------------- # Z4 V( A( H+ e8 M8 ]$ c& O7 B
ob_start(); //打开缓冲区 8 |# J0 |2 W+ \2 M* p" h
echo "Hello\n"; //输出
7 G2 z& w% Q, qheader(“location:index.php”); //把浏览器重定向到index.php   Q2 o, U) l) s& n8 ~
ob_end_flush();//输出全部内容到浏览器
3 |( J3 r- D" O: ]8 f; X/ W  U?>
: h& L, z2 w: o. f3 a3 T----------------------- 6 V8 n+ z5 W% @0 a1 x5 J
-----------------------
' F9 y& u  v) l# x& i" P所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 : Y# {: G( ~1 ~6 T. l* `
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我
, D2 X8 j+ X9 O/ b( D们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had * g% V- {/ B( g' i7 _# _
all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
2 G  U" R6 O+ X4 j( t$ q: a, w
5 U7 n" r9 I+ v6 L一、 相关函数简介: ; G1 U! N$ H0 s
1、Flush:刷新缓冲区的内容,输出。 ! K! n5 T( ?( f) w# l0 w5 G/ i* f
函数格式:flush()
% N4 f0 j( B: j! _# u, e6 D3 F说明:这个函数经常使用,效率很高。 ; u: X$ S, V7 D
2、ob_start :打开输出缓冲区 / ~# r8 ^) i& U! u" ?8 E: w! Q  u
函数格式:void ob_start(void)
( i3 G& E+ Y3 s1 N说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。 ( g/ d! R$ d7 n# O
为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
. t/ s/ D5 M6 l* q, [$ i3 、ob_get_contents :返回内部缓冲区的内容。
1 N7 ^/ G. o; J' `' g/ h使用方法:string ob_get_contents(void)
1 R/ L* U' E( J- W说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
2 ]' u! W. p4 N) d$ x4 d4、ob_get_length:返回内部缓冲区的长度。 / c) u- o: r, R+ G) r( E
使用方法:int ob_get_length(void) 3 s+ ^8 ~3 c2 O( U+ n
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激   f7 k/ s3 g1 U/ N: \
活。则返回 FALSE。
& Z" }: d% G" V) E$ ^( H0 _$ t4 n5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
* K6 a& X$ p' g" G使用方法:void ob_end_flush(void)
7 y0 F$ ^+ D+ Z( D, b+ V说明:这个函数发送输出缓冲区的内容(如果有的话)。
+ J& [% e) P& H6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区 7 n2 r. e" B( \4 T& I
使用方法:void ob_end_clean(void)
" {$ V4 G$ q; Y1 E9 R说明:这个函数不会输出内部缓冲区的内容而是把它删除! + ^) m5 Q  Q/ A' P
7、ob_implicit_flush:打开或关闭绝对刷新
+ u0 K* }$ J0 E8 }! G" K8 J! {: G使用方法:void ob_implicit_flush ([int flag])
2 N6 u, ^, e4 F8 w# x: W( M. \说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而
+ f, }& T( P9 N8 ~; G4 P! k* [9 d; P; I' Vob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
/ E7 j1 l3 g6 G接发送到浏览器,不再需要调用 flush()   h/ K+ K' n: @2 B/ {7 I+ A% D
8 w& m7 W1 o! u, B3 H( [
二、深入了解:
( c2 ?9 k5 X4 U3 B, v1. 关于Flush函数:
5 z/ z& V6 W' |# g% l这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
7 `6 K6 }, y( n- }% E的cache.我们举一个运行效果非常明显的例子来说明flush.
* O, u, `4 `8 c; n7 K+ DExample 2. $ L9 I  Z9 ~" Y7 u# w4 Z
---------------------------------
0 C. {# T+ p3 ?3 w( i6 ]! |--------------------------------- 3 r4 a: B9 k  M/ i9 Z
for( = 1; <= 300; ++ ) print(“ “);
/ C- s5 W0 w6 m! {6 N; `  D( Q// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 & t4 x$ ?* g5 i2 Q) }" K0 S  ~
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
5 i3 q) w1 X, u6 Z// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
5 {. E( [# k4 ^3 i/ m// 源源不断的被发送出去。
% O" _* `- F2 K$ n! }0 j* \For( = 1; <= 20; ++) {
, v' v- D# [) |- y" hecho .” % {! X  j. R: g9 `
”;
6 S, |  p  J3 h; ?: F( n- Dflush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上 . ~; E% f( s. B8 W
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚 6 O! e4 E* F% a& U" i' {- p) x
} % C* F7 f+ H( H' o& X: {4 ?
?> + e7 V9 ?0 N: i. y- ]. ^7 f9 P
---------------------------------
" A2 I2 c+ V8 h8 K% c7 D--------------------------------- 6 X& Q9 C2 s! P+ |
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php ( @8 \' \0 }( f5 @
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L , ^7 V" w9 A. P' |; l, O
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush
  ^6 g- ]  t% t5 T2 y(),这样做的好处是:提高效率!
! E4 ^: J3 t; U1 r4 A2. 关于ob系列函数: - |4 U/ E, |  W( B3 ^
我想先引用我的好朋友y10k的一个例子:
4 I1 g. M! L1 Z3 `Example 3.
6 ~' F! k8 V0 @8 P--------------------------------- ; {7 c& t$ z% l4 ]3 m
--------------------------------- # I/ r* t3 W$ r8 `
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
1 U, B. C, p% n- ~) m. u保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 + ^) ^" K# ?* J  u. }3 q6 A6 W7 @
缓冲区的控制,我们可以轻松的解决:
" e$ m( e9 S  B/ `---------------------------- ( o- t; |8 E; z3 I7 U( S6 @
ob_start(); //打开缓冲区
6 v1 j" T/ Z5 h% W1 X* lphpinfo(); //使用phpinfo函数
% s" z# g2 c3 S6 S- ]. `=ob_get_contents(); //得到缓冲区的内容并且赋值给 3 i+ @* [8 Q4 F7 {8 W& |7 o
=fopen('info.txt','w'); //打开文件info.txt
, e, i5 e& Y* K7 n# y% ofwrite(,); //写入信息到info.txt ' \# `  A" G# I; X+ k
fclose(); //关闭文件info.txt & V" r5 ~8 c8 g; F! _- m- {( J  R
?>
' K0 j( T2 \1 Y: B7 ?3 J0 Y4 F; C------------------------- 8 l, M9 q) V! r# N- X- O7 v7 U2 n/ v2 g
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上
7 _. B% F0 `/ Q9 E5 f; i4 p" w面就是将一些“过程”转化为“函数”的方法!   q0 X# K2 W5 x" j+ G6 i2 r! v" e' S
; a1 N+ Y" V, Z* u
或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语 2 U2 m/ L& n" Z5 |0 S
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
' a( _& x* }$ g2 J; D0 a调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
: J6 @8 D: P; P, \6 h了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/) [: ^- {  Y1 q$ e2 I6 q& Z
-------------------------------
5 X  O& H1 x. ?& A+ V-------------------------------
' ]- o3 L, \3 o2 w$ }可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌
/ Q5 W; T" W$ L( c. N握了使用ob_start()的要点。 * H7 [) k4 C( C* F% _9 @) Q8 N
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
4 z8 Q* P0 J# D+ c& N9 K(),ob_end_flush()(或程序执行完毕)之前不会被输出。 % Y& R0 F$ G% K
<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 / G% _( K& e: U2 @5 ^6 t1 d  O5 h  w+ Q% o
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后
' H8 M$ F6 v4 q. k7 p0 W自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得 , J# b  [1 B# G4 l  B" [3 r
到cache中的内容,然后再进行处理…… 5 @8 A7 f( `. |/ e! l, W0 O
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完
- c1 r6 \; Y) G+ ~& @, O, x毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。 : P% N5 B# a' _8 g  E2 J
来,让我们看看能用ob系列函数做些什么……
3 K; J  r6 w4 Q: Z( ~/ L& S& l一、 静态模版技术 4 ^6 U7 @% w( j" b- Z6 {& K4 G) Z2 a9 J
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页 . c4 e8 J! \+ X; d6 K1 X) g
面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用
6 f& Q8 S2 F( B' vPHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 9 ?6 a. R6 _8 f& `0 E' w
来的好处是非常巨大的。 ' {# i) k' ^, k! C/ a2 p
我所知道的实现静态输出的有两种办法:
8 O* k6 @$ w' V$ r. t/ U% x<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
! q. L3 Z; ]& l1 H" r<2>.使用ob系列函数实现。 0 {) R, {9 [# L. m# X: }: M
对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。 3 u$ s; {' v, }6 ?% b8 z) O# n
我们现在来看一看第二种方法的具体实现: 7 h" B- o3 M9 [8 ?
Example 4. 5 `$ {* A' @* `: g3 e( n
--------------------------------- . r2 E5 v/ p( K
--------------------------------- 5 }) [( t' T, D
ob_start();//打开缓冲区 / A4 B0 y% `& b* K+ V# H, ^
?>
* j" v" i& {' ^' F8 B; k5 Yphp页面的全部输出
7 e5 V8 B3 Y5 \$ B5 ?; R/ \0 Q) J& t= ob_get_contents();//取得php页面输出的全部内容 ! O2 ]8 l  \9 B& N4 B. P  ?
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入 0 [2 ~7 D2 r+ F8 w- [" N; `# }
fwrite(, ); //把php页面的内容全部写入output00001.html,然后…… 1 z) t1 k0 d' q4 \
fclose();
4 ^' M8 T% r1 V4 \0 X& Q9 e?> ! G# F' s4 Q! i4 z! D
---------------------------------
1 `! W6 m1 m$ \% k! M7 O0 A--------------------------------- 6 S  [' t0 x0 N9 E
这样,所谓的静态模版就很容易的被实现了……
6 }3 b, e' e- u二、 捕捉输出   b% H' x7 T: x9 X6 }: X* _
以上的Example 4.是一种最简单的情况,你还可以在写入前对
1 p0 F& ?6 l: J# Z你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 # i) ^2 d4 T* |  R/ \, ~! t# u) m
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的 8 Q! Z. m  z: _6 Q6 z4 S
想象力…… 7 F. m$ U5 }$ L5 U! f& s$ a1 |
Example 5.
+ T" N2 P9 _2 A1 e6 o4 x  T--------------------------------- ; T: }$ S! r, H& c
--------------------------------- ! M# J/ \6 f; _8 i  r2 b2 c
Function run_code() {
( N* R* y" x: z8 \+ L* l( oIf() { % ^0 U" P) @  X
ob_start();   R/ a" ^6 H- g5 a% t' W
eval();
" }$ s0 F: c( w/ P4 R  C= ob_get_contents(); 8 P/ x! s4 \3 a4 N8 B; j) {
ob_end_clean(); 0 `6 \- Z- B+ y7 [: Y8 Y+ |
}else {
8 F3 S' M& _" ^0 _5 U! _; b5 Xecho “错误!没有输出”; 2 K4 H7 M1 J$ ~- v  l& Q
exit();
5 f) `9 \6 K6 ^1 [) {4 E4 Q}
3 T  B4 A4 V; f5 F! T5 Freturn ; & d( r+ z/ Z/ K' T+ H6 l% p
}
- D: |  ]8 [  h+ \* t: N+ v+ [: u$ q--------------------------------
3 I4 v9 s$ Y8 H& i& d+ T---------------------------------
# e! ?  b" [9 m; }' c3 r1 N& C8 c0 b以上这个例子的用途不是很大,不过很典型 % y+ p0 G: _: X% o+ E/ L$ |: q6 {; g
子用eval把 2 V& b# j$ U  I5 ?# r8 {/ P  E2 |
Example 6. 加快传输 ; r$ `+ G5 @) E8 m% \* W
--------------------------------- - w2 z* m9 Y9 `+ n, c5 j
---------------------------------
% l) F% X9 A4 n/*
5 [$ a2 `0 L2 t** Title.........: PHP4 HTTP Compression Speeds up the Web
; f: v  F0 Q" [+ w$ ]* h" g- ]** Version.......: 1.20
' U# L1 m, Z) y* U** Author........: catoc 5 s$ N5 }$ m; I  i. U* p
** Filename......: gzdoc.php
  X; g! g% ?& W6 m$ k( X** Last changed..: 18/10/2000 + G4 |) a2 |% [/ X$ j
** Requirments...: PHP4 >= 4.0.1
( Y1 `# ?6 t/ b5 W** PHP was configured with --with-zlib[=DIR] $ Q) C. x" A0 g8 y( D
** Notes.........: Dynamic Content Acceleration compresses 5 P, e( O- l+ Y$ l$ K- w5 Z( T0 u! S
** the data transmission data on the fly
  q3 d- ?/ X% Q% t** code by sun jin hu (catoc) / u+ q0 _& y/ @4 z4 @) u
** Most newer browsers since 1998/1999 have
5 c4 l5 g5 `; N** been equipped to support the HTTP 1.1
2 U$ z; ]- W7 F5 [1 r; }# \2 B** standard known as "content-encoding." ) D/ L% w2 R0 m3 z7 q3 J  N$ I% M
** Essentially the browser indicates to the
4 M- S7 C* {  s+ ]* ]9 K( l** server that it can accept "content encoding" ' w& U! p# ]$ A  W& S6 D8 x5 s
** and if the server is capable it will then
  b5 I7 r/ L. Y) f5 C** compress the data and transmit it. The
- j" M- J4 z7 F% V7 W5 Q: c** browser decompresses it and then renders
" W+ }& |. G8 f** the page.
8 m4 o$ ]) N' U8 o7 v3 L** - @( l9 t6 ^& V1 P$ n: I8 E
** Modified by John Lim (jlim@natsoft.com.my) # O" w' u7 R( O
** based on ideas by Sandy McArthur, Jr * K2 @# X2 x6 A! X4 k/ a
** Usage........: - a; Y4 r& H4 S% O* I
** No space before the beginning of the first ' ** ------------Start of file---------
. W( ^7 c* W% u* {; N# k6 ^* n* \-
7 O9 N: v7 ?, X! r** │ ** │ include('gzdoc.php'); # J/ a! b9 [9 I% [, C& l1 }" K7 |
** │? >
% w. j; P, o/ ?8 b! Z0 M) e" a** │
$ [9 I7 P5 |) F3 F$ _1 J** │... the page ... * J' u+ m( }) o% |& O) o7 `
** │ $ z4 p9 j1 Y5 Q) x) ^# u: m& N
** │ ** │ gzdocout(); % n: c# S* d& n! q% c
** │? > / S' |% b$ I* f# R! X0 ~
** -------------End of file-----------
* A0 b' [( f% X+ h% N7 S*/ , M3 h1 w* w7 o, n9 L# Y& ?5 b
ob_start();
2 H: J9 M3 y8 s) q5 Vob_implicit_flush(0); 1 [! _( V. z! V7 ^' y9 }
function CheckCanGzip(){
9 c3 n, U% O6 z+ D. w, p( vglobal ;
3 k; N/ Z4 G& `# m1 T9 _! ]* d- f; rif (headers_sent() ││ connection_timeout() ││ connection_aborted()){
3 ~9 X" {- ^  _" E4 g/ S2 v6 Ereturn 0;
( K  l: H5 B* c# v7 ~6 X" @} ( ]; [) K9 w! P3 e9 ~1 a2 `; {
if (strpos(, 'x-gzip') !== false) return "x-gzip"; 9 S, r- H! G* Z0 S+ ~, y7 X6 t
if (strpos(,'gzip') !== false) return "gzip"; ) g( q/ O+ j. I: r0 F8 K, U
return 0;
# L0 [6 n% {; P* I} & F* r& v; @6 n8 w+ O
/* = compression level 0-9, 0=none, 9=max */ % v6 ?& v1 _9 i/ x6 a1 g6 k
function GzDocOut(=1,=0){ " P, d1 ]/ {% Z4 w6 L
= CheckCanGzip();
3 O  X7 E8 Y- y6 M  Mif (){ + z' q7 L/ o. C3 B, ^) y& t
print "\n\n"; . q3 u% V. P8 C* L) [2 \
= ob_get_contents(); * f$ n! f: [- Q$ B. t5 i5 C
ob_end_clean();
- m/ M" ^/ C( k6 U6 ~8 pif (){ " w1 {4 Y4 V% I1 A1 |7 P  R
= "
9 L7 Q, Z; s4 `# U1 `$ DNot compress length: ".strlen();
* o2 t; e9 ?# }* u.= "
, ]' C) F6 |5 \2 mCompressed length: ".strlen(gzcompress(,));
% E- s! m0 g/ D6 R.= ;
2 C& N! G) n1 Q% _" s1 X}
2 O2 t: X" J  y: [. ?/ ?header("Content-Encoding: "); & }( B: N9 K3 ^2 x/ K
print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; / y! q. R0 _! T. Q; r- f5 k
= strlen(); 4 C7 O" A+ I$ E0 G/ J
= crc32();
1 `$ A  ~2 D' G& o/ i= gzcompress(,); . ^# g1 {% b4 T
= substr(, 0, strlen() - 4); ; @  v) i3 E0 s% ?6 a$ M
print ; / Y! c& Y$ F) `( t) Y7 t
print pack('V',); # v! {% ?" f/ g
print pack('V',); 4 L! K5 k3 w' b  a9 T( M
exit; 2 b) p% D* X( e& W" c4 W+ o! L+ C
}else{ * g$ H/ g, s7 a. o( D
ob_end_flush();
& ~6 H; d5 \# ^, _exit; , s4 D" T  a% X7 o5 v6 h
} " v, `6 B* D( {5 G8 b
} ( ^, K. l& ~! Y7 `  E* X* X
?> / ?& R3 a* T/ J+ k; V4 L% B
-------------------------------------------------------------------------------------
% z- x2 d" }, G5 I2 X4 n- c# w$ C--------------------------------- ) Z9 b" a, V7 O/ Z5 I
这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内
. o2 e  ^6 m: ^0 R# w& L容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……1 @  q6 w" k7 X# M! p

! s) S! @1 W2 J) g参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html

也是支持,我代表大家顶你了! v; _8 O( C: `' K" F) a, M

: T% L4 s" X7 n  @4 B8 u$ f% `: t# o: l, z! s
$ \( j% w. z1 `5 q2 Q

! x$ M) ]4 g8 U* q% p6 `
+ I. j6 \1 ~" @* p, A- k
' q& j! h! h; o3 k. W5 a! s
2 c5 X- z& Z' K  `( w3 M: T6 q; D- |2 D7 S5 Z
, X2 H( Z/ W, A/ F# A! q1 N: _+ \, R5 M

$ m$ P$ j2 e' K) D, c  e  `" Z5 n" y9 o9 r! [0 k. T: @

( ?$ q4 s/ i# U/ A5 Q) Xmaiwenping.org

TOP

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