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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑 ' Y% }; J$ l( J) N( q  }" d
  u0 X' n' i/ R2 I& a
我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
9 G/ N) J$ C. Y! G# vExample 1.   c9 R8 b3 W/ `3 {
----------------------------
. r) {( o- ~: E& c----------------------------
2 Q5 `8 K7 {6 ~8 ~' E( tob_start(); //打开缓冲区
5 Y6 a5 P% B$ }! T& x& zecho "Hello\n"; //输出
; }) w: D- d7 p) i0 nheader(“location:index.php”); //把浏览器重定向到index.php
5 h5 f. p  C. S5 |ob_end_flush();//输出全部内容到浏览器 5 K; r7 l6 \0 D' R- J; v3 k0 ^
?> & h; I; [: ^+ P& W
-----------------------   l" q- O& }) C' Z9 |2 Q8 q
----------------------- 8 V. P! c7 @9 H  i% ?9 _
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用
; N, _5 k% J2 x& p3 c这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 ; `0 y" _4 C7 a7 q
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had
% Q( g" w& T- u8 j/ y3 k3 |all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
1 m: l3 R# `) n/ u
' z% I, r$ e. C" x一、 相关函数简介:
; j- f0 y% f1 r6 d% g9 w) B1、Flush:刷新缓冲区的内容,输出。   g& }" L9 A# W/ V
函数格式:flush() 4 k' H4 X: \# |4 {
说明:这个函数经常使用,效率很高。 ( i! g% g3 j; Z& v0 ]; m
2、ob_start :打开输出缓冲区
6 [5 X! y5 R( o% I6 D函数格式:void ob_start(void)
5 P7 h, S8 m1 q) ?1 P" f  I# t$ o1 [说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
( }& f+ D0 r) \$ E& Y6 N: f为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
* l) b( }& }# E/ I& _3 、ob_get_contents :返回内部缓冲区的内容。
: C4 O0 H) D& ~, ]+ x* S使用方法:string ob_get_contents(void)
3 Z, r0 s+ L- Z9 m/ B) J说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。 * c: I0 I5 D  E( r" a' N" S
4、ob_get_length:返回内部缓冲区的长度。 ( H- u6 @5 S6 p' o' T+ p1 ^  ?
使用方法:int ob_get_length(void)
1 q; Z& i) O# }) g说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激 3 K9 L: D! s* ~
活。则返回 FALSE。 $ [4 A3 J  M& t, L  s4 y
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。 & A% g/ k; b; f
使用方法:void ob_end_flush(void)
3 x- V, c* t- |) N- `5 x5 C' u说明:这个函数发送输出缓冲区的内容(如果有的话)。 . [9 U4 g  \) l. U  n
6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
6 t. k& J9 g+ k( h' K5 E. t+ a  v使用方法:void ob_end_clean(void)
/ z9 c1 h2 F. k+ e说明:这个函数不会输出内部缓冲区的内容而是把它删除! 5 x( k# b  I$ K) `% C1 s
7、ob_implicit_flush:打开或关闭绝对刷新 " }* y- H6 U0 C5 p
使用方法:void ob_implicit_flush ([int flag])
4 q" Q  B3 j" B/ C# w  L说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而
4 N9 A) c$ f" Y0 a1 z6 @ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
9 }1 f  }+ ?! o2 u& T. N. c9 e3 u接发送到浏览器,不再需要调用 flush() . a, O. t, `" v4 z8 d7 c

& Q, o4 m- {5 J6 h% g6 H' g4 B2 R二、深入了解: 1 R9 |, R5 g$ y. q6 d4 b& T
1. 关于Flush函数: 9 |! e3 S! c& i/ |! q
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
; E- [8 U" e1 f$ _! l的cache.我们举一个运行效果非常明显的例子来说明flush. ) Q! \4 ?% q7 `
Example 2.
1 K0 o) g0 t4 S2 G7 z& o---------------------------------   X( E! ?/ E# c# _# e
--------------------------------- " m! b! T3 d7 M$ f" x' [
for( = 1; <= 300; ++ ) print(“ “);
) v9 V7 R! ~5 G, q// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 7 c! r) l) M2 V0 u* x2 Q$ G
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
  l6 m' J9 h5 F// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
8 f5 w7 l( S* L// 源源不断的被发送出去。
+ D6 m% ]& e9 e- G+ pFor( = 1; <= 20; ++) { $ {. }* m& J- z) i1 P( w
echo .” , w# i5 k: |7 N' l5 p$ ~# _2 f
”;
% j' l1 f, g7 b. |7 }$ vflush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上 ' N) {+ A) N& q9 J: J9 }
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚
8 G5 m9 [4 @) W  k/ `6 I}
- W. |3 _$ w6 v1 a5 x2 I?>
1 z" {- s' b9 b1 Q---------------------------------
" @4 H- G! K8 |: K. d. `, k---------------------------------
' o) N% ^+ u4 o7 o0 a5 p具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
: w' ?6 Q! m  A* ^& ~  ]/ ~/ dPHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L ) b7 [) O& m+ P
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush % h# y5 Z+ C' e; H
(),这样做的好处是:提高效率! 4 l# Z. i6 M" _& W" }0 n
2. 关于ob系列函数:
- v* Y) e) e( ]$ A8 i& }我想先引用我的好朋友y10k的一个例子:
. V+ s4 ^2 i  N( aExample 3.
! b6 L2 C6 Y* S; y& K--------------------------------- 1 n5 |0 w) j5 v  n; n  }
---------------------------------
1 j7 k  g! L$ ^. [9 T5 a$ y) j5 g比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
: m( i6 I. C" R/ j' h- M; K" m/ J保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 * P1 c* O3 n( T& }* X
缓冲区的控制,我们可以轻松的解决: 7 z7 h7 P; w; ^7 ~" w
----------------------------
( S; q, H9 ~' C' Aob_start(); //打开缓冲区
0 |( J" d8 V' h. Z/ C9 {* lphpinfo(); //使用phpinfo函数
! C5 ^8 F6 U+ q& a6 C=ob_get_contents(); //得到缓冲区的内容并且赋值给
  V9 D* S8 D/ f2 X5 V=fopen('info.txt','w'); //打开文件info.txt 9 @# g6 R& h! T& Y& S, F
fwrite(,); //写入信息到info.txt
7 O/ c# K* n# C% S# o1 n  c: Bfclose(); //关闭文件info.txt
9 y8 e2 r8 ]. m1 p; i) c?>
6 p, f  H( C$ q------------------------- ( d$ ^* @' j! v# w
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上
, ~5 U% x, }) j5 J9 e面就是将一些“过程”转化为“函数”的方法! : e  |- f( t# J, q

$ B& A6 C' I+ s或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语 ! b: t  d1 ^' E1 C  e
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
- k# E5 D  h7 \' B3 |调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
1 e3 c$ ^' b2 g0 G了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/7 l- q* M1 D6 U
-------------------------------
' ?2 y- @8 H$ f5 |5 }+ e- C. D) u" `-------------------------------
7 i: b) U, Y4 m& v0 F可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌
  B! K  [. K/ {1 _* ~' ?( A握了使用ob_start()的要点。 0 W4 ?+ p1 e- u: e
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush $ w7 s& v. c" ]) |* X4 }* W
(),ob_end_flush()(或程序执行完毕)之前不会被输出。 3 J" J) Z" J: x2 M; k
<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 ; ~# i8 u! o; g3 p
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后 ; K/ f/ j3 {, L6 `( e
自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得 6 {0 n! i# y: Z, ]9 ^
到cache中的内容,然后再进行处理……
- {1 D* s* }. G& A<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 ( q9 U0 X" ^* a9 ^" I
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。 ! |4 l6 P( w9 n2 z8 z! s
来,让我们看看能用ob系列函数做些什么…… 4 N- E/ l- n; i
一、 静态模版技术 " G5 x7 a" z% l, U
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页
0 o. [- B# K5 v% C面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用 # [5 n. @( f& y4 x& S9 {$ ]0 C& K, T
PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 , q' z. |# y9 m$ X+ q) N4 O
来的好处是非常巨大的。
+ _& N9 x% o- b8 y6 Q$ Q我所知道的实现静态输出的有两种办法:
( o1 c! s2 _- N* o7 j<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。 ( W# m' w- v: V, H
<2>.使用ob系列函数实现。
! q+ ~& |, l# H, W6 [/ u  n对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
6 z* V$ U6 @+ ]; @" c6 _我们现在来看一看第二种方法的具体实现:
4 t& x# z8 G1 O1 vExample 4. . z  r+ _# S& m7 Y, c( j; x
---------------------------------
) h8 D' s8 Z$ g) m2 x6 z: u& a* \--------------------------------- . I+ q! [7 @. Y/ m8 K  L, C
ob_start();//打开缓冲区 7 T/ }  j1 m9 K4 F
?>
+ |: i" H/ l( p' W* G0 Rphp页面的全部输出 ( ?/ m6 K' d  s, S! b
= ob_get_contents();//取得php页面输出的全部内容 1 ]; m0 j6 }7 S1 P5 @
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入 7 Y: D; b9 Y2 H8 H% }4 q( E! S/ W
fwrite(, ); //把php页面的内容全部写入output00001.html,然后……
5 h$ n( B4 Y) h8 K  [. zfclose(); ; k+ g! p# N3 G2 B
?>
/ F, B1 [8 i" E--------------------------------- % l! R* ?( F; e+ W) ]
--------------------------------- % u: d$ e; R# z$ ~
这样,所谓的静态模版就很容易的被实现了……
3 ~% ]$ g0 x7 u, p7 z6 P  ^# \二、 捕捉输出
# t0 s6 p. o7 S5 J以上的Example 4.是一种最简单的情况,你还可以在写入前对
% [2 \, U. f7 f" U% u$ U你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 9 o+ y" y. D: u
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的 5 e7 _) X' W$ M% @4 i& N2 ?8 n* t
想象力…… , S; F9 v  Q  g( [4 s) s& O
Example 5.
' Z( _. P+ N2 Z* g---------------------------------
$ u( q# f/ v3 t) \0 {8 {---------------------------------
4 c% ~' E; N1 J2 {( JFunction run_code() {
8 \4 t; q' P1 `$ a. m4 ], EIf() { " u5 o* h( d" `" Y
ob_start(); : v, X6 r$ f2 j: d/ F- }
eval(); & D( t# T0 z4 L- A6 L& i' P, C
= ob_get_contents();
/ k9 @4 t" C0 a! U9 V* qob_end_clean(); ( x6 Z& R0 r0 D) l5 n* r  ~* _0 \
}else { ; H$ M* U/ M4 b
echo “错误!没有输出”;
/ ?( d) K* K  Q; V  G2 c" k& Bexit();
- z4 [! H* |# t( V} 7 `+ n2 F( e: w/ D+ n; x: ~
return ; & B* O, Z  ?- @$ L
}
4 |& e3 I1 \; A' y--------------------------------
) ~3 O* U$ M5 Q0 p  [* A--------------------------------- 0 @( W& V: }; Y
以上这个例子的用途不是很大,不过很典型 1 y% O; y2 ^2 Z9 P8 \0 e
子用eval把 4 F% a1 n6 E9 M/ Z6 L
Example 6. 加快传输 . a4 R9 L4 G. n) o
--------------------------------- . u4 `3 u  c8 D! D$ I% _; [2 ~) \
--------------------------------- + l" T5 D' b! m/ w: [
/*
/ j9 \) y8 K; m** Title.........: PHP4 HTTP Compression Speeds up the Web ( m7 V+ ~& k* P2 a7 p/ Q
** Version.......: 1.20
$ E' G& T0 Z1 R. P% H! T' S, p** Author........: catoc
) X3 @7 R* ~: N, Y** Filename......: gzdoc.php
  P  q: ~: v6 A** Last changed..: 18/10/2000 ! ]# I0 j. o# |9 p" p! K$ l4 q
** Requirments...: PHP4 >= 4.0.1 4 x3 M) f" x* A+ y; T
** PHP was configured with --with-zlib[=DIR]
: O/ I! N4 O: p0 T7 V** Notes.........: Dynamic Content Acceleration compresses
4 _* N$ a1 u: z! ~! V' O** the data transmission data on the fly ! ?2 R! V6 z8 n! A5 |
** code by sun jin hu (catoc)
' f- O. L* H, v8 ~** Most newer browsers since 1998/1999 have
4 b. K5 ^% O7 c# a- D. [, S** been equipped to support the HTTP 1.1
7 ?# W, ?, k+ a* f( E** standard known as "content-encoding."
; y: X4 U, N7 T, }" e/ R# G, g** Essentially the browser indicates to the
' T" t; Z9 ~; T** server that it can accept "content encoding" ) b  N# S& G5 E/ n% ~! ~+ w
** and if the server is capable it will then - l/ M7 b8 R! \5 L3 H
** compress the data and transmit it. The 4 [& H1 f  V* A8 Y/ A, A4 T! y
** browser decompresses it and then renders " ]. e5 p* V8 ?. j, x" q2 J
** the page. 9 c" Q( f- d% p
** $ c8 J2 G& I/ T6 i7 O+ D
** Modified by John Lim (jlim@natsoft.com.my)
- M% S3 [; L0 P* b8 L* ]/ B** based on ideas by Sandy McArthur, Jr 7 Q! q( S$ v  i+ q2 x4 Y9 h
** Usage........: 8 a7 G% W' M; P% G
** No space before the beginning of the first ' ** ------------Start of file--------- 0 d3 ]( G5 r0 G3 b
-
- R, l5 E1 K7 j: R+ O, E  Y** │ ** │ include('gzdoc.php');
6 l8 f- h5 ?% ~7 a% I** │? >
& o8 s) E' @7 Z* D' m* w# `/ Z' F** │ , M, z0 {9 A5 ?4 B# @7 y! Q
** │... the page ...
3 l0 b! e0 ]6 Q% G- v4 V** │ 3 n/ p. W- L6 ~5 i0 U) A
** │ ** │ gzdocout();
; B7 I# B! t0 j9 r' M3 k** │? >
+ B! w# B" M( y: ]% \9 h& w3 Y) c** -------------End of file-----------
. N4 e- F- f) y( D*/
6 N6 o& N+ ~8 t6 ?3 I* Y7 y8 ]ob_start(); + J7 q) d& x+ w; J* C
ob_implicit_flush(0);
0 X* H$ F# U% r4 N, |# Bfunction CheckCanGzip(){
$ f0 Y1 r7 c3 Y1 r- z) a8 bglobal ; . Y& I/ v/ m; n7 f. B0 M3 j
if (headers_sent() ││ connection_timeout() ││ connection_aborted()){
# m9 w8 D4 D; zreturn 0;
& l: g" N' ^5 M* D8 L- i}
$ q8 @" G7 X2 ?% c: P) Qif (strpos(, 'x-gzip') !== false) return "x-gzip";
" D  T0 o, l' @: w  G: v! q0 n. A  mif (strpos(,'gzip') !== false) return "gzip";
1 A9 V0 f: n. v$ u0 M! V, f. areturn 0; , @7 S: f5 U% }  c
} 9 d- R' @. S$ C! W# M; p. |
/* = compression level 0-9, 0=none, 9=max */ 1 [, d2 w4 T/ j# X1 d) I
function GzDocOut(=1,=0){
: e2 S9 w! L& V! P1 w; P: L= CheckCanGzip();
6 l$ E6 j" |/ `$ q. Jif (){ 5 y, r; _+ F, z2 f. f
print "\n\n"; * Z. n1 L5 I7 h8 n
= ob_get_contents();
+ p2 L/ f5 O. {7 l, fob_end_clean(); ! K8 }8 a% t! V, r' U$ k
if (){ ( m' v; `% m7 ^
= "
3 E2 O+ `7 t1 l+ ?+ J3 INot compress length: ".strlen();
, e- Z! x) u) N) s9 y.= " " F9 q5 T9 j9 R3 K* \2 ^0 B
Compressed length: ".strlen(gzcompress(,));
: t: Y) a  q  @.= ;
4 _7 {, R8 Q) K( x, Q0 C} ( |, G  G8 D, @. r  f: r
header("Content-Encoding: ");
# h; z1 U4 ]- @( a: S- tprint "\x1f\x8b\x08\x00\x00\x00\x00\x00"; , h7 S$ h/ K- U' O6 g6 Z4 M% I4 T
= strlen(); 7 U1 ]0 {' z: e! z0 j* `
= crc32(); . a) y5 J; Q! }7 O% F
= gzcompress(,);
5 S6 s& P! ~9 D6 L  k9 @= substr(, 0, strlen() - 4);
/ Y9 s% @8 D$ Aprint ; 5 i. t' v1 w9 s) d
print pack('V',); 8 B4 I+ I! A. M
print pack('V',);
- q. ^& K# O, e7 b" A( J7 Z" Xexit;
% R+ U3 d- s% x( q* }) U}else{ # x2 t* l. b* _* [( c7 y" |# v% x2 _
ob_end_flush(); * C4 C9 G( f% I! {2 J6 h
exit; 3 l0 Y' ^( _9 D& Q# e' l, U6 Y+ W
} 9 h+ {* ~! b8 Y/ X2 _: |
} / D" o" b9 ~2 x. ?7 }- x
?> / c, c  H& ^1 m+ f+ e# y
-------------------------------------------------------------------------------------
  N7 ]' F4 M- e--------------------------------- 3 _# O$ D$ G" h
这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 0 `: x: B: V/ }+ _7 M" n
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……
/ X. |; Q4 }2 ^: j8 x; s3 S& k$ x8 \8 W2 Y* B4 f6 G
参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html

也是支持,我代表大家顶你了
5 D# w- \5 E7 F( [3 v& Q
# ^9 A8 X; S! R0 z2 }
- q' y6 F5 ]3 l$ v7 h! g  z& D7 U9 v1 E; G: e5 Q
* q6 U7 P7 t0 X- }2 f
3 U2 _/ U% W. g: ^

! K( S* ?) E5 C6 w4 ?
+ P, ^- i5 W1 O% t9 @
8 Y" W; Q: H# Z9 E& @; S2 D! E
; R9 [* V) l6 Z  S/ M7 E* B! |, M, m" R8 w+ V" L

( S0 U$ u7 X$ c# ~0 g: e
6 `" M: Q& \& L" Omaiwenping.org

TOP

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