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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑 ; t. ^& _7 t% J- @- @

1 t! X$ ?$ _' A$ ?, n我们先举一个简单的例子,让大家对Output Control有一个大致的印象: 7 {7 P2 [. D0 M' {& S
Example 1. & p4 i. ]- H. U: e
----------------------------
4 @$ I( R3 T: E8 f# c---------------------------- - C$ x+ B; q" k
ob_start(); //打开缓冲区
! k. l6 W( l3 L$ |0 X! N  e2 Yecho "Hello\n"; //输出 4 k: x/ _! m$ m  p
header(“location:index.php”); //把浏览器重定向到index.php
2 Y- p1 E5 L. e& |* Q) i5 `5 ]ob_end_flush();//输出全部内容到浏览器
6 Z9 `( i7 S2 X, H1 ~?> ' v; D5 b1 d8 F" a9 ~& H" O
----------------------- 4 V3 s- \& f0 l" B
----------------------- , z0 I7 |1 I; W4 u1 {" \
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用
% a3 d( T& w0 V这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 # M6 T* y& m9 p3 g
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had
% g& a* }: n- k& E& M% `0 _all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
0 P6 T; Y+ J& n. Y+ w7 K/ K8 N6 N0 U; C9 [8 y7 S+ x1 ~) y
一、 相关函数简介:   ]0 n& w1 l) E* R1 D) l8 d
1、Flush:刷新缓冲区的内容,输出。
) h( ^9 r8 y( O5 i$ ]1 c1 P函数格式:flush()
/ ~" K, |, }% h* W0 ~% ?& r说明:这个函数经常使用,效率很高。
1 x  N5 X6 W3 ~2、ob_start :打开输出缓冲区 / f6 A# U; f( _) [: ~) F/ J
函数格式:void ob_start(void) . F) h+ b0 |: i
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
7 s6 Y0 ^3 R* r/ Y$ E8 I- u为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。 7 L% h# L. G) c" B; p$ v$ b/ G9 c
3 、ob_get_contents :返回内部缓冲区的内容。 ' _& |3 R5 f6 ~, f/ o# q
使用方法:string ob_get_contents(void)
3 x8 x# f( L7 j说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
( P+ K0 x5 P4 ^- e) J4、ob_get_length:返回内部缓冲区的长度。 4 v9 Y2 G6 D) Q6 C, o' V( I/ ^
使用方法:int ob_get_length(void)
. A1 u& n6 m, h: l说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
5 W0 c$ Q' ^( q/ o: @活。则返回 FALSE。
6 ~, p5 j1 n" P. \2 B5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
/ m# n% W9 X& Z& g使用方法:void ob_end_flush(void)
0 c; |) e8 i& E) G% M4 V说明:这个函数发送输出缓冲区的内容(如果有的话)。 ) e2 t9 d( n: I7 {( `
6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
5 z' i. h: a# D7 o) G% k使用方法:void ob_end_clean(void)
! @) C4 s% @$ R2 [/ _说明:这个函数不会输出内部缓冲区的内容而是把它删除!
/ h- f# V$ h) v5 S7 n4 e8 Y7、ob_implicit_flush:打开或关闭绝对刷新
2 M  @0 \6 I# G  {* O  h使用方法:void ob_implicit_flush ([int flag])
' F  _$ ]* g) A1 R  v  @& l说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而 $ b& \0 x" l' l4 T( s1 G) n+ x0 }
ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
0 G' q( Y  t2 p) S. R2 `接发送到浏览器,不再需要调用 flush()
* o1 H' m) J, i7 _7 O
' {; Y# e2 z2 r8 j# S二、深入了解:
! `8 T5 d) M' ]1. 关于Flush函数:
. k! c& h6 u4 V2 w2 M: n; D这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
! J9 Z( T7 A3 I  r1 j" i0 f的cache.我们举一个运行效果非常明显的例子来说明flush. 8 L. P$ R/ }" V1 E# }( C) p6 c# G
Example 2. " s6 J5 e% O$ g+ Y7 w4 a
---------------------------------
0 D+ t4 V9 I; N' Y$ m1 ]---------------------------------
4 \) P9 q* z' u6 M" _$ hfor( = 1; <= 300; ++ ) print(“ “); ) N8 f) z2 a& A; T
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 . V* p: l0 p# A. L' W% V" g: |
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
& Z8 E8 }9 i# V( g// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
2 k- L! o4 C$ j8 f. Z: R8 r// 源源不断的被发送出去。
" f$ M1 z1 ~3 B7 c* TFor( = 1; <= 20; ++) { ( h; b, V( O( W" W' _
echo .”
* |: B# _9 Z# A0 R8 `”; $ r8 G$ y3 m6 L0 ^# B% _$ y2 @
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
9 U$ J, |6 \2 |sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚 ! v0 }2 b0 n1 U7 l( |' F
}
6 S2 B# ^6 {: w& r' F?>
) R; x* t7 f, }0 Q8 x: v* t---------------------------------
  A* [! K# H7 _" w# Q4 o+ _3 T: n* L---------------------------------
, y' j. u' i, P5 Y, f1 p具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php ' F/ \4 o4 v# e8 O9 K
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L " s* `2 c$ E) z9 p
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush
8 z5 l' v3 g/ V5 i(),这样做的好处是:提高效率! 6 ^1 Y: `0 @2 }2 k- d* Z& K
2. 关于ob系列函数:
/ {2 ~, r  h3 Y3 n我想先引用我的好朋友y10k的一个例子: 5 Q  i1 Z1 _4 V4 q; p
Example 3.
) R3 U4 S  p# j, ~4 h- C---------------------------------
& c2 R6 I; Y0 K- |( J5 w" B--------------------------------- $ H/ O! B  D3 X) a: C# G4 C
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
. a8 g2 P# h1 f保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了
2 w- b) s* i4 {. W& P( c6 p缓冲区的控制,我们可以轻松的解决: 5 o  `, l0 W; w6 c1 ^
---------------------------- # f  z$ {5 {- e
ob_start(); //打开缓冲区 " v7 w5 k' U$ L
phpinfo(); //使用phpinfo函数
6 t. d0 k4 O; |$ K7 O8 B9 l/ O=ob_get_contents(); //得到缓冲区的内容并且赋值给
# w/ @+ V  \8 v1 W1 Y# s( {=fopen('info.txt','w'); //打开文件info.txt
4 Y* }! J8 u/ k2 u% ]& h1 Yfwrite(,); //写入信息到info.txt
# A6 f: A& _8 u5 Pfclose(); //关闭文件info.txt 1 X5 R9 ]+ D' x' g+ W, [' v
?>
  A7 V0 J6 V% m+ `-------------------------
- Z0 L9 G  u9 r% V1 j用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上 ; ?# @3 |  t9 }8 Y1 U
面就是将一些“过程”转化为“函数”的方法! & x$ l9 h3 ^9 A  h* i+ A

; L5 I  n+ ^% G. K6 y) H) B. T或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语 ; X. b( `5 B4 n
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
; d% l6 L, K, e* q( o* Y4 A调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
5 W' t8 _( p& @3 L* e4 E; N( Y了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/
/ g+ _3 b6 d* c$ X------------------------------- 4 ?, H9 {8 O  R2 I
-------------------------------
' ~! B4 H% w  ?( C可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌 5 s7 N) N6 C' ?* N8 M
握了使用ob_start()的要点。
8 I; M( C0 e9 r! m$ I: ^' b<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
4 b# D; G+ [$ E2 F/ {(),ob_end_flush()(或程序执行完毕)之前不会被输出。
3 s* C; i) s/ N: u6 m0 F. N# M<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及
7 {& `- }5 A- Z' T: lsession,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后
3 T. Y  K, }5 X* i0 q自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得
* _% @% S2 o9 ^9 b3 [/ W到cache中的内容,然后再进行处理……
$ w! j' ~9 R' i) I: V- C% ^<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完
  q9 W: U7 T# c5 \% `毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。 " a% J8 H$ X3 C" W; M
来,让我们看看能用ob系列函数做些什么…… , C1 S% X* }' T6 u* x( n
一、 静态模版技术
7 R4 p3 A- J% T6 J简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页 ( }: V; \9 A" ~. z$ B0 h, L/ @6 Q) n
面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用 3 A1 T' o: }% A5 s
PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 5 I1 w- r/ X$ i6 o& j0 j; G
来的好处是非常巨大的。 + b: W' Q) ~( v, J* a
我所知道的实现静态输出的有两种办法: 2 }: s. v$ R. ~& w5 i
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
+ ^" A5 D% h5 M7 U<2>.使用ob系列函数实现。
; n! Y* x3 D5 {; i6 ~" V; w% P对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
+ A# x2 i4 j% E! B" R; a我们现在来看一看第二种方法的具体实现:
( q  L8 P5 R; W; H- RExample 4. & F# V  k3 \* s! L
---------------------------------
8 F: n& w5 o: i# v--------------------------------- $ v3 ^8 k! j+ F1 x1 n1 c
ob_start();//打开缓冲区
" m/ u: X7 i! h* G/ b0 r?>
& f0 ]  w9 K1 F( J2 ]php页面的全部输出
4 V3 T7 \( @5 B, c= ob_get_contents();//取得php页面输出的全部内容 * S* c# c! L& d, w
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
* q& ~4 B& g) S. f0 Tfwrite(, ); //把php页面的内容全部写入output00001.html,然后…… # W7 U  i8 T1 o8 f4 i% R
fclose(); ; M$ P# F  \% O
?> 6 C8 T# Y* u! @" W3 I) O# T
---------------------------------
& A$ y% m6 W$ L3 v$ q--------------------------------- 0 t" e8 k0 ?5 M( k; N& m7 v
这样,所谓的静态模版就很容易的被实现了…… 0 h9 _+ J- P6 Q$ V( a, u
二、 捕捉输出 4 x; {! [3 |7 r2 X# m! t0 \
以上的Example 4.是一种最简单的情况,你还可以在写入前对
3 x$ Z% ]  F* q. J% B+ J5 R& ?/ x你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 $ L) N  J8 \0 k" v. z" V9 ~2 p. ~
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
% F1 q% J6 w2 N# G想象力…… * S& ]( N  y9 r
Example 5.
4 j5 g" k! v2 ?0 S  N---------------------------------
7 d& ~2 Q. y, v0 d3 {: A--------------------------------- - P. t! v6 f9 ]9 ]
Function run_code() { $ f3 W  y8 M7 ~
If() {
! z& l( _% m- B+ W+ |; ^' T/ zob_start();
! h/ i$ M  C% u" j/ [' A6 Qeval(); / @' T# l) ~/ o2 K
= ob_get_contents(); " k- |$ F' E2 J; u7 M
ob_end_clean(); 4 v- U3 J4 K  h3 U6 G1 m
}else {
6 j9 Z0 X  z5 A$ x$ C  Yecho “错误!没有输出”;
9 J4 Q3 y: e; U# A5 R# Texit();
) L6 Y: z8 F* ?# F  ~' L} 0 P. V- y, d& S$ N" N
return ;
( M  y9 \2 [3 s" [}
7 Z" Q3 y  }( s& S4 H2 s2 z% t--------------------------------
9 v- a: V# }& a- Z---------------------------------
( ?0 p2 t6 P* H, g. D: Z- k( o以上这个例子的用途不是很大,不过很典型 " b  A, w: p$ t3 v8 s' g9 h) @
子用eval把
4 [" o6 ?1 H9 O& Z+ g: k: O6 f8 gExample 6. 加快传输 % I5 F/ A) |; b- N: T5 v/ W
---------------------------------
# s0 Q) c, r. m' }# G--------------------------------- & W5 Y2 v2 i$ B) j8 ^
/*
6 {2 n6 z6 p& V# J) t* A6 l** Title.........: PHP4 HTTP Compression Speeds up the Web % o' k& F6 i/ `# \- ?* k  F
** Version.......: 1.20 3 v+ G: c- B+ J4 {* S
** Author........: catoc 1 Y5 f1 E- d# ?6 T& y7 i* l
** Filename......: gzdoc.php & K: f1 b3 H# u* S$ z, {1 ^" I
** Last changed..: 18/10/2000
  E  \" a7 e' a! Y# t** Requirments...: PHP4 >= 4.0.1 / b, N' `% P; s; R# o3 r& K
** PHP was configured with --with-zlib[=DIR] 8 \7 k' q) k, q) i' r1 F( @
** Notes.........: Dynamic Content Acceleration compresses ) P% M( u8 ?( M( @1 x7 ^. y; f
** the data transmission data on the fly : w& M# w) W/ h, {, C7 r
** code by sun jin hu (catoc)
+ A/ T) \9 J8 d$ ]/ g" q0 o6 g( W" X** Most newer browsers since 1998/1999 have & T4 t$ V' W6 ?$ z9 }
** been equipped to support the HTTP 1.1
1 I+ X" t7 f4 Y1 B% W( {1 b: D8 _** standard known as "content-encoding."
% `4 i! \' t$ R" a1 d% b2 h** Essentially the browser indicates to the : X7 a5 L5 ?% p6 @! e8 O
** server that it can accept "content encoding"
# _$ Q* @$ W1 t. H, t** and if the server is capable it will then ! ^# f- Q. H  j% K9 I
** compress the data and transmit it. The - u; [: W& ]+ e7 K8 a' l
** browser decompresses it and then renders ' Z+ n% s, j& h$ B  }& o
** the page. : u6 Z9 d8 h; T" ~
**
% q, g/ h' O: S2 n: Q* }** Modified by John Lim (jlim@natsoft.com.my) 3 U7 a: b9 U& Z
** based on ideas by Sandy McArthur, Jr % O. t9 V1 T3 X- ]* B) R: P" Q1 [' k
** Usage........: * s  a  R4 J) |6 |" C( Q
** No space before the beginning of the first ' ** ------------Start of file--------- 5 b! v# f2 q9 D
- 5 s6 j6 L# E8 W1 i
** │ ** │ include('gzdoc.php'); - {% {$ q1 x: `$ v
** │? > $ y: J; e* Z& n* G0 V; Y' _* e6 p9 f
** │ / f9 v8 k! h: [4 l8 i
** │... the page ... " W4 ?  g- K# t& C0 @
** │
, Q+ q, {  `# ^** │ ** │ gzdocout();
& m7 g5 D5 z6 o' L5 z. Q- g2 {** │? > ! o2 e* h; `8 |$ ~7 I6 O: V
** -------------End of file-----------
0 M+ F2 F0 U1 n*/
6 S3 V; e2 H+ e0 z; Xob_start();
$ O: Z( N! `7 x2 `0 q* Iob_implicit_flush(0);
8 X* y8 C4 h& A& |6 c3 ~function CheckCanGzip(){ % i; s! w* w9 l
global ;
  H! z% K% j/ m# pif (headers_sent() ││ connection_timeout() ││ connection_aborted()){
) r, G9 g# @/ _) [return 0; " y/ }  ^& ?8 C( V0 l3 W0 }; g
} 2 {9 G2 ^: U6 @, }( C1 E7 d) i: `5 u
if (strpos(, 'x-gzip') !== false) return "x-gzip"; 2 t2 G' t: R% J* `, M; K
if (strpos(,'gzip') !== false) return "gzip"; 9 I4 a* H" A0 o2 S2 I6 b( v4 p
return 0;
* D3 Z$ c, }1 S7 c4 H, N# @0 R} / C, Y; R$ r) W
/* = compression level 0-9, 0=none, 9=max */ # H/ I1 @2 d) Y$ W1 V
function GzDocOut(=1,=0){ 6 U  r9 j) o! q# T: F( A$ k
= CheckCanGzip();
4 N) u: S3 c( o+ V0 O- Z1 q9 }if (){
* B8 u9 r) L; s1 a+ v) i( ^, [' m# Lprint "\n\n"; & q  X# T2 v# L
= ob_get_contents();
9 C  }. E1 `% ]5 s9 aob_end_clean(); ; v. ?$ ]1 K" X& m) ]  w1 O
if (){ % b/ ?7 ?+ n, C( b. t& \( g) g
= "
2 Q! \0 p( I) B3 j  N4 n! qNot compress length: ".strlen(); , ~- E0 `8 V" E
.= " ) X# o# X  |2 D
Compressed length: ".strlen(gzcompress(,)); * E$ n0 Q$ J0 E" Y/ \5 V2 A
.= ;
) ?  @8 V) Q% d$ {}
; y) s  j! E" k0 ^header("Content-Encoding: "); ' R* [# X- }1 w& D6 p5 {' P( X
print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; % O$ z0 J: g: ]4 [1 K. k
= strlen(); / ]. \  C/ b, h1 A0 ^7 Z/ o0 O
= crc32();
" a; c! d* Z% m# H0 [3 T0 U/ e= gzcompress(,); 1 J1 b8 C5 }( p& l& O$ W
= substr(, 0, strlen() - 4); : G4 [1 |  @. x, q& V
print ;
) ]2 L6 G! ]0 V2 p' E6 Q/ }print pack('V',); ( L% U4 m) F# L* S9 G9 U, c' a
print pack('V',);
0 P) o7 |* t6 N# g8 mexit;
9 F0 P4 }6 w+ ^9 Z+ _}else{
% I4 D+ w, O7 @6 f2 Job_end_flush();
% C, ~2 i$ c& ~& lexit; 3 N/ W8 J5 C; ~& d) m
} # D$ E# T7 U0 G" G6 t( ]9 ~. R8 `
} ; q4 c+ f8 n$ l; h8 E0 C1 o
?>
9 F" \! b! Y/ O  @9 p; n1 |------------------------------------------------------------------------------------- ; S/ X& L% j  K) V  {
---------------------------------
. f) Z" ?; o/ N1 k3 c( ?这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 5 V- V& J2 |. y. n' \$ C( a3 ]
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……
: h, O2 H3 x% ~9 b, l- S& W6 h( B# o3 k$ w5 C
参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html


也是支持,我代表大家顶你了; I% x& U& b) J% z: _
$ x3 X  \, v1 v. E/ ?" c

# E+ N7 X0 k- {" W& ]) d8 X- q9 R
5 @2 v# Q  b' ]- U# A  N' o1 g: t4 U( Y% y
, H  q- N9 }+ d; _' R& l

! l, {5 x# K' }0 z9 _  t) e: ]  ]0 {8 }. T! K: P. \4 H- ?2 c

0 A2 w0 s% k7 u8 N
( w: T* p. D; Q) n7 I3 B5 F" c5 _# F. K3 f7 {/ T
, z  y+ e4 C! y
7 S; p. Y6 p+ Y2 I
maiwenping.org

TOP

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