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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑
7 F1 [8 B. D% f9 L) E2 R% e, b# T3 ~6 ~1 P  A5 y8 t% v( v
我们先举一个简单的例子,让大家对Output Control有一个大致的印象: . X& f. I5 I- w( O: z/ R2 a( D
Example 1.
2 }- {! _$ g/ t" p6 R9 D. d1 i! `----------------------------
+ v4 O# ~& w2 g7 n$ U---------------------------- / D+ ~* z" o1 S
ob_start(); //打开缓冲区 9 w0 T# ]+ X" }
echo "Hello\n"; //输出
9 c9 y& R$ M* G7 mheader(“location:index.php”); //把浏览器重定向到index.php 6 g  I- o. @+ f6 F" k+ N
ob_end_flush();//输出全部内容到浏览器
* R1 J6 |' v# b$ z' V" r: q?> 5 A  u) s) s# c. k& f6 q5 B2 d
-----------------------
% n$ P0 a: }$ p7 e: Z( b----------------------- / p% L* w" g* F1 s. y6 J
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 0 @2 @4 P. k5 a5 V3 P. d
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我 ) [1 d6 y  i% W+ k0 S. e
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had
3 i& X' C0 k7 C5 _6 Tall ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
3 j+ s$ y- ^3 s6 G+ C# H
% L! a$ J7 F0 j8 b8 q; i一、 相关函数简介:
# P6 B  l5 J! h) b5 u0 T1、Flush:刷新缓冲区的内容,输出。
4 y9 B2 ^# K: r7 g% m7 p函数格式:flush()
# ?' \9 l6 x3 Z. m3 K说明:这个函数经常使用,效率很高。 + H$ Q0 w, G9 V& F
2、ob_start :打开输出缓冲区 , G, r" t0 B5 W6 Q" s: O
函数格式:void ob_start(void) - L# B: Z. ^+ I, R+ @+ N
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。 ) B7 Z: c' `! D0 \% \
为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
2 w1 @" X" y! x* j$ h7 a! C2 A3 、ob_get_contents :返回内部缓冲区的内容。
* I# [/ Y9 r0 Y, z使用方法:string ob_get_contents(void)
) t, r( |3 N4 x6 O  H, h* h说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
7 L/ d+ r6 E; [/ m4、ob_get_length:返回内部缓冲区的长度。
  P# H2 \6 e9 u% w# r+ m- Y使用方法:int ob_get_length(void)
( d: n! j" a4 y6 u说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
6 f4 K: X# D) W. v0 O活。则返回 FALSE。
5 H# y9 P! W1 M& q( C' Q/ W/ c# E2 T  O5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
) b! o0 }' g7 q3 y使用方法:void ob_end_flush(void)
$ c8 J& T% }5 U' c1 d3 q说明:这个函数发送输出缓冲区的内容(如果有的话)。
: p: a5 Z5 T4 I, J0 P7 h6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
% B7 M  u: s* G  H) U9 E7 \使用方法:void ob_end_clean(void)
5 c" L- @' `: B( y3 W说明:这个函数不会输出内部缓冲区的内容而是把它删除! 6 ~# d% n6 q" w, r
7、ob_implicit_flush:打开或关闭绝对刷新 2 J8 v# J7 I8 [/ d
使用方法:void ob_implicit_flush ([int flag])
( n& {5 q0 Y' q  z3 @/ s说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而 . V2 h" h" h* [6 g8 n
ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
  Z+ p7 k; V! }/ m0 y" D接发送到浏览器,不再需要调用 flush() 7 w! l) d; _& Z" Z2 ^, r4 h; l
  v5 y' @9 |$ O6 B( i, r3 e
二、深入了解: 3 g0 V7 H4 e. x) V7 e0 t6 f
1. 关于Flush函数:
+ W( ^7 Y5 F! ]3 Q这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
: }* A- g8 r7 h的cache.我们举一个运行效果非常明显的例子来说明flush.
3 Q4 L6 D( n4 h4 m; GExample 2.
6 M9 G: p8 l; W' y- T--------------------------------- + P. E" n; w, o
---------------------------------
, Y3 U* ?8 B5 Y0 c) |* p$ H' Ufor( = 1; <= 300; ++ ) print(“ “); / f( \7 U2 J+ V: W( s
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
% d0 v) @" u  ~& K- ]5 _// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经 2 r9 ]5 p6 s5 ~1 V2 a
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
/ C5 ?, }1 ?  f/ o- y- N// 源源不断的被发送出去。
2 ~/ E0 n* F" S, x/ uFor( = 1; <= 20; ++) { 7 x) M% i! p: D8 R- ^  K+ f
echo .” 5 D! B) f: b4 Q- C+ M
”; 4 i  e. Y* h  x7 `1 m4 _: ?7 n
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上 - B, I/ t  K/ B% ^3 Y5 W) E$ Z
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚 4 |9 ]# n: G9 b  u
} " S8 B& U  x' T6 w# |* x4 C
?> * }6 c& F; X* u; q/ a
--------------------------------- # @6 h( p5 K1 g
--------------------------------- : u; k1 M5 R# g5 v
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
2 f. v4 r8 F" h% \6 nPHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L 1 ]6 ?- S2 p( V2 K0 ?% r+ [, j
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush
8 P$ f2 }1 s& b' [3 h( x; D, v; c(),这样做的好处是:提高效率!
. G1 v$ s; Q0 S3 ^5 W: D5 ?2. 关于ob系列函数:
/ P- u; f1 N( S! A/ P我想先引用我的好朋友y10k的一个例子: , @' q8 ~3 T0 o$ o
Example 3.
. E4 Q) [- t6 V* a% L2 W: H* F--------------------------------- ' T4 c4 `- I! d; u* C$ `( L& N
--------------------------------- - M6 j0 x4 U( d6 H$ G( L" R  l' D
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要 ! J+ s- H" w' z% b: f
保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了
! i' R- ]% l2 g缓冲区的控制,我们可以轻松的解决: 3 N' j8 e- ~) k0 n
----------------------------
  P3 A1 @3 J4 Uob_start(); //打开缓冲区
' S' h/ a1 f4 U% M8 jphpinfo(); //使用phpinfo函数 , P* @& s3 S2 b3 d& {
=ob_get_contents(); //得到缓冲区的内容并且赋值给   d: d6 T& X2 p5 k* n/ J& Y) M
=fopen('info.txt','w'); //打开文件info.txt % {! i% L, O8 x: a
fwrite(,); //写入信息到info.txt
- h8 C, @% g( v1 Efclose(); //关闭文件info.txt 2 Z  \' z! b* X1 D0 j, ~6 y
?>
8 u: E! f' _4 D1 Q1 ~4 ?------------------------- ; c1 @: p* Z6 Z' Q
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上 , |; R0 ]1 M4 ~* }0 y
面就是将一些“过程”转化为“函数”的方法! % E0 v0 v2 s2 U( j+ M
1 U9 ^. j9 B; `! S" G7 B
或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语
4 {) ]" z% q: x. [8 m+ l, \法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次 + h6 k/ f/ ^& c
调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
* U3 v( V+ O, a+ e; W了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/
6 a1 B7 q2 B( `* ~9 z! h------------------------------- : I$ J6 q& p; M2 j3 d
------------------------------- 3 O6 e$ d) y* e( Q7 p* X" [! P
可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌 # ?" Y! C6 o' A# O
握了使用ob_start()的要点。
: G  C: p( V$ h# w9 ]<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
0 m% O  }: q- K( t8 {(),ob_end_flush()(或程序执行完毕)之前不会被输出。
0 X$ w0 {* h3 e& H) P3 P2 P<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 - t2 f& M5 Q+ n
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后 , d" S  n4 A" R" o
自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得
5 L* }! E+ y, ]$ r& G到cache中的内容,然后再进行处理…… 6 l9 b  `$ r2 K
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 ! e3 l& Q2 `' Z& {* P( c
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。   `" ?: u# b3 [- @: q
来,让我们看看能用ob系列函数做些什么……
! i9 q- u" f; }, l' e一、 静态模版技术 : G2 F" l$ V. ^  C* f8 d" I% y
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页 ! |: [" S) r5 e
面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用
) M+ u$ e7 h, K9 T2 aPHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带 $ X5 e& |3 W0 O
来的好处是非常巨大的。
# F: u8 i# M3 w) k我所知道的实现静态输出的有两种办法: ( p- a9 k( o( R7 m2 k, [
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。 # [- |" |: W! Q+ {* x$ ]
<2>.使用ob系列函数实现。
3 E8 Z( s' T% S" b+ e对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
8 I: w  ~1 H# t8 l- ]' {我们现在来看一看第二种方法的具体实现:
. A7 V; U8 Z7 S+ |5 f# c: [Example 4.   P% w6 e% V2 J4 A
--------------------------------- ' Q7 i7 Q! C) s' _( M$ o1 O( @
---------------------------------
* B+ g1 J( @- D! a4 T/ ]- @+ u4 Y+ Cob_start();//打开缓冲区 5 f6 N0 h% V# x+ L# l- T9 U
?> 8 D5 j+ Q2 e2 K6 p- n1 X# u
php页面的全部输出 , K4 [/ W0 b) L6 u. b. s: @
= ob_get_contents();//取得php页面输出的全部内容 6 N. s* W& U$ a/ k1 ~
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入 # T; M& s! K" ~% {% u3 d# {6 K* B% O9 M4 c
fwrite(, ); //把php页面的内容全部写入output00001.html,然后……
1 n4 b. {5 W4 L1 ~$ H: Z9 Ofclose(); 2 [( n. L7 {5 {/ a7 S! t5 y7 m5 l5 f
?> ' _* R5 X7 `5 F" W$ a. l
---------------------------------
; a4 Z( K* C5 Q---------------------------------
0 R2 K" A4 G9 t3 O4 x这样,所谓的静态模版就很容易的被实现了……
6 @; D( O' ~1 I+ @+ H, v: w" S二、 捕捉输出 ' T4 D+ ^% P$ B" A
以上的Example 4.是一种最简单的情况,你还可以在写入前对
$ M3 S! [: L# w4 n) j你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。
' L( H. \( p! Q/ ~个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
" b4 J5 Y8 f. V" v; v想象力…… 8 B9 \: s, S) X
Example 5. # }$ u% S9 W* U2 A* _
---------------------------------
. e6 S: |1 h$ H# W. M8 f: c  h---------------------------------
# v6 O3 q  J) t' C8 ~8 ?Function run_code() { 3 O6 O' q0 l8 a
If() { 9 }. a2 m' f- _+ b  e, {
ob_start(); ( y* l4 E+ W' W% s1 O
eval();   ~* ], _5 w' Z* l9 |
= ob_get_contents();
* f. z* o* s; S* a  oob_end_clean(); # J) D$ ?% C3 ~+ `" O
}else {
4 z6 j; K, i. V, g. B# s; Cecho “错误!没有输出”; 5 k2 M" l- _5 ~% e2 ?9 @
exit(); 5 \/ `4 h# O, I" W2 M7 r- W
} 6 J. ^) W. }% }
return ;
+ i% `' i& a. u2 D} # V3 c. n; `0 A, b9 Z) C2 `* i
-------------------------------- - B( y. ~/ E0 x( d
--------------------------------- " A0 z8 m: ?4 n* z) k
以上这个例子的用途不是很大,不过很典型
, S# b' m8 E0 p# {子用eval把 9 |) j% c) ^% _% N7 o
Example 6. 加快传输 , l- r) x2 K7 H" t1 w. [* d" I
---------------------------------
8 j5 n1 h2 [9 N; }---------------------------------
2 w: g5 {; S5 K8 r$ I/* % N, L( L5 c4 Z& l6 D$ a+ \5 j
** Title.........: PHP4 HTTP Compression Speeds up the Web 2 E/ F0 \" O9 K; S% p4 ~
** Version.......: 1.20
# L3 C  z# f5 i** Author........: catoc
' u% P0 G0 T2 A% i8 v1 U** Filename......: gzdoc.php
* d  {% ]& y* ^1 W** Last changed..: 18/10/2000 1 E. v' V. y% q2 o
** Requirments...: PHP4 >= 4.0.1
8 c6 d2 w0 I) o** PHP was configured with --with-zlib[=DIR] / {- y3 S8 w; x* y6 |5 k
** Notes.........: Dynamic Content Acceleration compresses 1 W' p# P; w) h, M& m( u
** the data transmission data on the fly
" V; b) L/ x7 u% J3 z** code by sun jin hu (catoc) 5 f4 [4 u/ w3 O) F
** Most newer browsers since 1998/1999 have
8 u: i4 A" m/ o/ K** been equipped to support the HTTP 1.1
/ X4 A) O! [: I. B- f* _  p** standard known as "content-encoding." 1 c' T' W) B% {) A# f
** Essentially the browser indicates to the
1 M' I! r$ Z7 d: S4 b9 \** server that it can accept "content encoding"
5 R8 q! S: q6 X" B# ?/ g** and if the server is capable it will then
7 O5 v) `3 T, P** compress the data and transmit it. The 6 B" N) A% p. Z& Q8 p, J. v
** browser decompresses it and then renders " P/ |. r* F" K- a9 {: J
** the page.
( C, ^5 A. u3 y6 v**
* y- W3 H; T0 x1 n$ C7 V1 m** Modified by John Lim (jlim@natsoft.com.my) - C1 N* J7 e4 q: ?' Q% u
** based on ideas by Sandy McArthur, Jr 4 P% X. a6 C' F8 u
** Usage........: # H& \* x* p; L1 i' Z& a
** No space before the beginning of the first ' ** ------------Start of file--------- $ t: v# K( C" W
-
* Z) P- [* z9 v  w/ |) L** │ ** │ include('gzdoc.php');
) X  t$ T9 B% ~4 l3 s4 l** │? > " X6 Q4 u4 j9 Y& p* O
** │ % t* I) i, A2 x3 F* \
** │... the page ... 9 v% K7 z  {4 U' J/ A
** │ & \( Q6 V& `" y/ R6 j: [- k3 p
** │ ** │ gzdocout(); 9 s  q- C0 ]4 H$ A$ v) @
** │? >
  N% \* G" v4 B- k5 W: t6 v. b** -------------End of file----------- % X# c+ j7 M/ ^. j. R. u: T( F
*/
1 O0 ?. L& L6 a% ^ob_start(); / _: y# g: v9 x
ob_implicit_flush(0);
. C: ~/ U4 d: V$ y5 a( Pfunction CheckCanGzip(){   o" S4 k0 L# @" N% @+ M( K
global ;
: p) y& F. e( J# \4 _0 e" bif (headers_sent() ││ connection_timeout() ││ connection_aborted()){ $ x8 u. [' |  e) ]8 B+ F
return 0; 1 Y4 k/ Z$ k7 `: {. [5 g
} % G2 a7 `( N" l
if (strpos(, 'x-gzip') !== false) return "x-gzip"; 3 |, u, W, s& p1 U  n% Z! E
if (strpos(,'gzip') !== false) return "gzip";
& ?2 f" i7 N, _4 L$ Ireturn 0;
: ?" U7 E# q' W$ K# w} % C- U* |9 H7 _# K
/* = compression level 0-9, 0=none, 9=max */ # ]0 \$ B' I; D2 v
function GzDocOut(=1,=0){ ( y( d  u8 R: ]  F) R/ u
= CheckCanGzip(); ; K  ~) Q7 H1 n$ C- U$ R6 Y
if (){ ( U# K' E1 T8 F1 L
print "\n\n"; ) h0 q" Q% d/ V7 k; ^$ m
= ob_get_contents();
6 m. ]2 K3 H& S, G1 cob_end_clean(); 5 q- V# g- S! t# ^' C6 F
if (){ , w4 ]$ F/ R# R6 d, U+ M) Y3 c
= "
4 n# s4 v/ {  S/ [, Q# CNot compress length: ".strlen(); " V& J$ W. n" f8 p: z
.= "
4 q0 C8 k/ S! n: B! |9 ~. q8 E' lCompressed length: ".strlen(gzcompress(,)); 0 s$ q- _8 R% f
.= ; 9 n" L9 f) M* _5 X0 {
}
' v8 m2 _; w9 a5 ]header("Content-Encoding: "); : [9 X0 N' A' X- C
print "\x1f\x8b\x08\x00\x00\x00\x00\x00"; ) F1 g4 c. h( [9 y% {
= strlen(); ) }0 |  h2 T8 \( G! o$ h) B0 Q: p! j
= crc32();
- T, @" ]0 f9 m. X( F3 _= gzcompress(,); ( c) r4 G6 b* U9 l) a5 H; [
= substr(, 0, strlen() - 4); 6 X. v: _( r) c
print ;
, d9 ~$ I0 f4 z( y( q2 c+ wprint pack('V',); ) Y4 j- V5 s9 x! W
print pack('V',);
2 c" C/ K  f2 ?exit; ! P3 t& J! d! ]
}else{
% P4 k& s. j6 r  D" ~ob_end_flush(); / S+ Q! F0 e, a  f* Y
exit;
, h( v3 s8 C- u' O+ W# g}
5 u3 p& ~' O! ~' G9 T" O}
! _: P4 B: \9 C! B' @3 W$ H( b6 O?> . h' _- j. _* [
-------------------------------------------------------------------------------------
' F. Z# r& k; e---------------------------------
$ c& W# x: _% T6 F+ z这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内
2 Q2 O) g' y3 {) B容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……) a5 M0 M$ K3 P$ d" X

8 L8 U  Z, S) _! t+ c3 Q+ D参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html

也是支持,我代表大家顶你了  f* t( {! \: c$ y
/ e( u2 [/ x7 e& c; l* p
2 D: ~& c: E$ M: B# S
% s& N: z0 Y( A9 q  e
0 }& e( K, W/ w9 I
9 n' L! L5 C7 n  X7 M
' C: |$ k4 Q! }( ~4 O0 t+ X

9 j, D+ n) q7 A4 ]% \
0 R" t( A; p1 G6 r7 R. d1 G9 n* J
: I8 J& g- S7 W9 q) k5 Q3 ?
" v1 p  Y; ?2 g$ b% G' o3 X; k5 Q, e1 u3 W% v

; p7 ?, q# j8 h' u8 N. C2 I8 Imaiwenping.org

TOP

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