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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑
% E. v5 K$ q( ]
0 a# b1 H! x+ ], }% W. a3 w2 m: ^我们先举一个简单的例子,让大家对Output Control有一个大致的印象: : w% e: k! X* M
Example 1. 6 V$ A9 G, o8 [4 h& \0 o
---------------------------- , ~3 b* H  h0 z# d: T. Y3 `# _
----------------------------
- s' X2 B5 }; g$ Z: I, z' X% b3 aob_start(); //打开缓冲区 ; }* K" m8 n' u$ ]2 T- m
echo "Hello\n"; //输出 / i8 }' u- w  m0 Y! ]: k5 @$ P
header(“location:index.php”); //把浏览器重定向到index.php
! b9 d5 |8 z5 F* _: aob_end_flush();//输出全部内容到浏览器
7 D2 w+ }2 ]: r/ W2 {/ S2 Q?>
- @' L; r( C% @-----------------------
' q: `; p3 S8 y4 s2 g/ N9 K-----------------------
' J4 {; r+ S* |+ e9 \所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 1 v  o8 [/ s3 E- @* H; N
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我   m. k1 x7 l# L% N/ g: v
们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had - z; [& z# l( J5 N6 Q0 L9 O
all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误! 2 w) I5 L) k. m; X, F
( _- R& r' m+ w
一、 相关函数简介:
( P# ~6 J# \/ B6 I! x  D' v1 h1、Flush:刷新缓冲区的内容,输出。 ! o5 w1 t* P1 C) }
函数格式:flush()
' l, |  d# N/ Y* n. {+ L2 b说明:这个函数经常使用,效率很高。 2 x( Y5 m# B" `" h6 t# V2 Q1 r$ Y
2、ob_start :打开输出缓冲区
3 y+ L( u, k" i4 i$ s- ^' }函数格式:void ob_start(void) 1 u. c! y3 Z# g5 E
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
1 S% b" a8 o* k为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
' @+ B) \. o  T3 、ob_get_contents :返回内部缓冲区的内容。
/ v5 J0 ]: w8 C. z5 Y, s使用方法:string ob_get_contents(void)
- d8 U. |4 M/ E* @说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。 2 o) p  g1 c; Y, D9 w
4、ob_get_length:返回内部缓冲区的长度。
& N) g% C1 Z7 ?4 I% q7 [使用方法:int ob_get_length(void) 9 T7 i# b; x+ R& E9 E) X1 q' V
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激
; m) Z( ]- s. h活。则返回 FALSE。
" @: o2 Y2 ~6 A7 t& x5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
4 B7 W* H# b/ t# G$ w  }使用方法:void ob_end_flush(void)
) H/ E0 j5 W! F  U7 w. ]说明:这个函数发送输出缓冲区的内容(如果有的话)。
* N- x% }/ O% T" {& Z4 @) r- D& L6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区 2 a7 o7 w7 z1 H& X9 c( b/ h
使用方法:void ob_end_clean(void)
- E; q1 O% t: k# p说明:这个函数不会输出内部缓冲区的内容而是把它删除!
' h7 g; A. ]/ x- O9 w- N7、ob_implicit_flush:打开或关闭绝对刷新 % t- `0 W* }5 m" U
使用方法:void ob_implicit_flush ([int flag])
, r. w# E$ _* V0 g# p2 M% ^  |说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而 : A  i  v1 v9 \+ S8 i5 T% x1 Q$ V! x
ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直
3 Y5 s/ C( Q& i7 u8 {' J: l- V+ r接发送到浏览器,不再需要调用 flush()
" U/ L3 |$ O4 r! v0 p1 A% N/ B3 v. T0 \$ d
二、深入了解: ( C( \' m2 q5 e
1. 关于Flush函数: " o) p. q8 U' U2 G
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser 3 o- E2 d4 v/ o2 q8 D
的cache.我们举一个运行效果非常明显的例子来说明flush.
/ Y1 a5 u1 R( IExample 2.
; R- X6 j- J) f; _; q$ T--------------------------------- * o) B' q! f) `- r
--------------------------------- 3 }# x4 w) n+ Z; H+ N4 q  S) Y& X
for( = 1; <= 300; ++ ) print(“ “); & g, O6 I& o5 l3 K$ o
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出 / y0 c0 ]9 h' ?, h" E$ x5 g
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经 ! r7 N( @1 L) c" W$ U& P3 Z5 n
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
" i& F# d8 e7 O+ b// 源源不断的被发送出去。 ( c" ~+ T( v( q: E7 o: Y' O) n* y
For( = 1; <= 20; ++) { * ^7 e1 s( F! ~6 M( J2 x& H2 l1 `
echo .”
: _4 K) e( ]5 k”; ! p3 ?" C6 A2 z% ^4 C, b
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
* {3 n5 ^3 F3 U1 ~/ Q3 wsleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚
7 F. k0 y0 h0 k- V# q9 r" t" k# @& t}
, A$ j8 V6 E: p8 S, ]?> & N8 q( M) L2 O2 p2 r1 B
---------------------------------
# i; k; Y7 \* k) @  R--------------------------------- : p" w. j0 Z1 W- L. L
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php % S( F9 s9 C. E
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L
3 F. s$ z  m$ ~& M注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush 7 U9 A" d4 w  I) g& a  j' }# Y
(),这样做的好处是:提高效率!
' a2 l+ ^; a# Z1 h$ b2. 关于ob系列函数:
$ H+ h& [4 M* N  q  D( h我想先引用我的好朋友y10k的一个例子: ! I! _4 `. z5 H2 I
Example 3. ) y7 a" [" u, n2 N4 J
---------------------------------
  k/ l# I/ [9 X) l( J--------------------------------- $ @0 n3 J- h8 N, T4 k
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
0 O! b5 [+ H/ ]0 ~8 C- B6 s保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 8 k( G3 z# A4 J; x: D6 v
缓冲区的控制,我们可以轻松的解决:
+ V' i% }7 S$ t----------------------------
1 i9 u6 @& W' Bob_start(); //打开缓冲区 3 q; t5 i, \1 S5 Y
phpinfo(); //使用phpinfo函数 ) O  g. v6 b) K. [5 w5 u4 h4 j
=ob_get_contents(); //得到缓冲区的内容并且赋值给 1 v  o$ b$ l" C# w3 ~: ?4 K
=fopen('info.txt','w'); //打开文件info.txt 1 S) e6 v  h: K) }. `" [
fwrite(,); //写入信息到info.txt
# n; t8 L$ |% Y1 e, P/ K8 hfclose(); //关闭文件info.txt
2 ?" q  o" `: t9 p?>
( P8 |2 W! p1 \  o2 b% ^. N  S) O-------------------------
6 {6 U# ]- \) h$ E用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上   v, `, ~- [/ p6 v  l6 F
面就是将一些“过程”转化为“函数”的方法! . [+ l$ S, j2 x: B5 i8 c- L
4 I# }8 b4 L+ `$ |! i1 ~
或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语 " n+ o1 S! F# V2 {2 j  A, p
法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次
( @6 l1 @. m( r7 K( v  A调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留
" f5 U' I8 a3 T0 r. H8 l; K# a了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/& G6 I& I' V" I" Q3 C
------------------------------- - g8 S" q; H+ T( C, _( `
-------------------------------
9 u: o5 }. h2 u0 @. x! @可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌
* l7 k+ Z- t7 X" Q1 C% B握了使用ob_start()的要点。 1 m2 W4 ?& t" E% d5 n
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
% x8 G, l* m7 M1 y) D0 Y% e& H3 B(),ob_end_flush()(或程序执行完毕)之前不会被输出。
# i( |- |, W3 J7 K3 r<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及 5 m3 G$ C9 I: @0 m
session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后
- X+ B. e) X6 Y: M自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得
. X% b+ Y9 X; M) t. s( o9 @7 w, v到cache中的内容,然后再进行处理…… . v4 M: }" B1 M! O
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完 2 q" r3 ]8 J1 m+ w& u
毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。 ' Y/ j. u: E' z3 i4 B9 F
来,让我们看看能用ob系列函数做些什么……
) L6 b2 ~8 }% ]: k一、 静态模版技术
3 t: f- J1 r0 N6 T- G* G7 M8 G6 Q简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页
% ?( A( P# r! \: q+ E1 i) W: n) L面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用
5 }; I/ C( n) \PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带
; h9 W" ?* j( y5 j7 ]6 _/ }, g; M来的好处是非常巨大的。
0 x- Y# T+ B% W4 _* g+ O我所知道的实现静态输出的有两种办法: ( i5 q  L5 @6 B5 n5 v
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
/ N& C6 R& @! {# {# O. N<2>.使用ob系列函数实现。
, k  Q) d6 j: Y' L) k. [" F对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。 % E' [- I5 u) y, L1 W7 R4 M
我们现在来看一看第二种方法的具体实现:
8 E2 _$ _- l1 {& }8 xExample 4.
! [# s$ Z6 \& L---------------------------------
$ B/ l6 ?6 R( ^* }---------------------------------
9 y$ G% j, s9 Rob_start();//打开缓冲区 + F/ k' T/ W6 i9 @$ _; |* Y1 i
?> - E" q& t7 T" ?$ o+ b4 i
php页面的全部输出
4 z; W' v4 A# v7 o! E) S  U3 I5 X( ?= ob_get_contents();//取得php页面输出的全部内容 , [" l) Y, D+ N6 s
= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入 9 w/ _& R$ y0 M! z* q
fwrite(, ); //把php页面的内容全部写入output00001.html,然后……   |) @! L& ]( K, Y7 T  O
fclose();
! K9 w1 h3 \2 e& K8 O! F% I( I?> ( k' f0 a/ |9 t( k, Z$ ]
--------------------------------- / O( a7 E; U' R. b1 |0 \, w- I
---------------------------------
% d# i" _# I; Z6 @这样,所谓的静态模版就很容易的被实现了…… 0 ?9 z2 W) ]' F# H# r0 p' F; u
二、 捕捉输出 % Z! k6 S0 i; }' `/ F
以上的Example 4.是一种最简单的情况,你还可以在写入前对
. z# G4 ~- k. n' ~& A1 t$ \你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。 ! r! e0 ^7 U2 }; _! G
个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
6 t$ g1 Q$ L# K2 o) p( x0 \3 j想象力…… / u8 q3 I- I8 Y& {( o- J0 Q; m: k
Example 5. ) o9 u1 p0 P( w$ v- n0 f" B
---------------------------------
( o! t9 P# b& f2 g* w* P2 N--------------------------------- : C& b+ _  L+ B1 E: R8 i
Function run_code() { 3 T) [/ N% _8 A4 Q5 O8 e# @
If() { ( O2 m& W9 T# J3 v5 s" H
ob_start(); 8 a/ U7 d7 E  g6 `7 o/ t
eval(); - N* o  `9 T% h4 c; o7 R" o
= ob_get_contents(); " X  y8 ?, \- ^5 j5 @, m9 k
ob_end_clean();
8 _! R/ j/ N% d$ G4 g1 ?  k9 [}else {
$ Y, W- \) P6 G! h) [* ]8 Yecho “错误!没有输出”; & T6 D2 [( t( O. I+ k+ ^
exit();
: S4 Q" U* V, W: _}
- q) l$ _) Z4 z& a8 O/ E3 Dreturn ;
' G6 c: X- _2 o% W  s}
  b$ q, X0 Y- }8 z! R4 P4 R- M; N( s3 @--------------------------------
5 q1 L1 \) T" L! P$ ?' K--------------------------------- ' @# W1 ?% `  z$ \" s
以上这个例子的用途不是很大,不过很典型
2 F+ E) n5 ~! F4 z子用eval把 ! l, T" s# F: E3 |3 C
Example 6. 加快传输 : O: ?$ c! o* B! e: r; k! r
---------------------------------
' E% [' k2 O7 Q- M$ L--------------------------------- 6 h* T& {  Y/ N! T
/*
* v8 X- {( J7 }+ `* H** Title.........: PHP4 HTTP Compression Speeds up the Web , |" A* I2 M. g* e
** Version.......: 1.20
" ]/ _9 p7 L) J+ R( _) k** Author........: catoc , I+ F+ N6 q# {
** Filename......: gzdoc.php 8 m2 ^! Y' \( I
** Last changed..: 18/10/2000 8 d3 M# A5 h: p0 H1 h6 P: A
** Requirments...: PHP4 >= 4.0.1
; ?/ H  ?8 |' u( U0 T! h! A** PHP was configured with --with-zlib[=DIR] ( j" b% [9 J9 L" _6 p. \
** Notes.........: Dynamic Content Acceleration compresses $ Y5 G% X2 Y7 k! Y$ ]7 L
** the data transmission data on the fly * c' s' m+ o; S: W2 k5 m; i
** code by sun jin hu (catoc) " l8 v, q) }& D5 e+ E1 U+ I
** Most newer browsers since 1998/1999 have % I, g: j5 f3 ?, f
** been equipped to support the HTTP 1.1
" v) S- `. Z  u3 W' Z9 Z6 b** standard known as "content-encoding."
% F" C7 n2 m( A: C** Essentially the browser indicates to the
' P. _+ N1 g+ D9 `9 a8 {** server that it can accept "content encoding"
; l+ [) D1 s5 B' A** and if the server is capable it will then
' |4 E* a6 R( I  l% I** compress the data and transmit it. The
7 z) N2 z6 Q0 l: G5 `: C** browser decompresses it and then renders $ ?0 e* L3 P8 D  ]; H8 v
** the page.
( j: v% `( v$ J4 ]* m0 q**
; R4 G4 p% v* y9 B. e* o** Modified by John Lim (jlim@natsoft.com.my)
7 F# Y0 L8 o6 S0 |' C** based on ideas by Sandy McArthur, Jr , l/ \  S# B! c$ ^% C
** Usage........: . j9 K- ?) E- b2 _4 L
** No space before the beginning of the first ' ** ------------Start of file---------
2 a  l8 R1 w* h2 ]/ u0 h-
/ Q# w. |4 g7 K! p* \4 w** │ ** │ include('gzdoc.php'); " b4 W- g  U; N/ z1 y
** │? >
0 p( S: y6 g( B** │
" _$ y; W( U1 I& G. {** │... the page ... 5 a$ {: A: ?+ k' Y- O! g
** │ / r* \6 g) ~9 C, J5 W4 ?- q1 w
** │ ** │ gzdocout(); - h. {) ]+ O& D: ]
** │? >
- t) a$ Y; Q! D1 h& F** -------------End of file----------- ' U- H  N8 K" B3 W1 Q3 e
*/ 1 Q# d# W$ I2 R3 P! p- T& l
ob_start();
0 E* b6 B4 a. N( y+ {! z" F; Zob_implicit_flush(0);
% k1 P/ `% \" B+ y) z; D5 d' Sfunction CheckCanGzip(){ 6 \% @, T! j7 O3 L6 _
global ; 4 ]* r$ z! L( j% h& ]
if (headers_sent() ││ connection_timeout() ││ connection_aborted()){ 2 }4 K* G( J' C5 Q3 C1 N8 V# D
return 0; 0 k9 s. a% b% s6 e5 F# R6 {8 S
} * K, d; ^, e% ^
if (strpos(, 'x-gzip') !== false) return "x-gzip";
$ S6 V6 \5 N1 z; ~6 Rif (strpos(,'gzip') !== false) return "gzip";
, W$ [" H, y* C5 k. M2 Lreturn 0;
% r  a; }* l( G* G/ j- L} 9 \; c: f/ v1 d
/* = compression level 0-9, 0=none, 9=max */
% f3 C$ o6 C: r9 _& {/ {function GzDocOut(=1,=0){
2 [. _4 z& P+ `3 {3 J4 @; l= CheckCanGzip();
2 [0 c- ]( E1 E' ]; [if (){ ) s- s0 n2 z# m; M
print "\n\n"; 3 D, _+ a4 W2 j% H/ {  J+ s& C
= ob_get_contents();
  \: N5 _- J( H& K& x( F1 Bob_end_clean();   z& ?, Y% n! X4 y) S
if (){ - r0 i9 D/ H# P+ w3 p: X
= " " T6 ?1 p$ n' S
Not compress length: ".strlen(); 0 R# n0 m# [+ A- f0 P
.= " ( _8 y9 C7 i: |+ n0 r
Compressed length: ".strlen(gzcompress(,));
/ o* [: t: P/ z! K7 N! {.= ; 7 o7 k5 U! P7 l5 J7 c
} * R5 X% i9 h) A4 l% e: J
header("Content-Encoding: "); ; e( B* Y8 m# U( o' F* q; M; n) B
print "\x1f\x8b\x08\x00\x00\x00\x00\x00";
. S1 N8 `& q' P" B+ u# J1 \= strlen(); . N' a0 |, W" p# p& a- v: T
= crc32(); 7 P  o6 ^$ K3 X  C3 ]% n
= gzcompress(,);
$ @9 r; z  v0 Y$ d- ?9 c4 ?1 C% e' N= substr(, 0, strlen() - 4); 1 k- C! _: b6 q( v* V6 \1 l
print ;
4 l5 k/ \% Y8 [; I0 n7 aprint pack('V',);
0 t; d, P5 i- P( o& bprint pack('V',);
: B# T  O- x/ u9 L% H+ oexit;
) @" `8 `3 I0 z; h4 b4 z+ c- A: ?, \}else{
: _* L/ o9 y& j! [- Zob_end_flush();
& U, l) _3 [/ b5 r* [- gexit; 5 M7 ?, G. H% P  {
} & K* Y( n, ~; Z. ~6 `3 }: t
} ) M8 y5 W0 |: n1 {
?>
5 u: ]- A" q7 o6 _-------------------------------------------------------------------------------------
: _7 c3 X( W3 e( b. D# S& b. m--------------------------------- / V" F0 o" B! w- I, P+ b0 r
这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 . {$ N1 v& Q# F; V8 k# M
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……- J% R8 N% Z$ x% |3 K9 S8 D
2 O; G% F6 h0 {! R7 D
参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html

也是支持,我代表大家顶你了- V# [. P+ I* T8 G! p
, P, [+ e. ~1 U

+ y4 d$ W" f5 R4 c: q) ]' u: i# P  n6 H7 a1 @( j9 G

, C/ y+ k5 u4 t1 {; X
1 l8 [; I' @" i6 V) ?0 N# \
# C! e* ?9 A# i/ e  l
9 F2 d/ d+ A" M: ]! z: ?# n, M( s5 j! i% |& c% E& f  Q- M

7 C  b7 E7 c7 |1 o% d
1 X4 q' O% n2 R7 u; g) O2 Z
( s6 U. H- w0 L- T$ @8 i; q' d" [9 l
maiwenping.org




TOP

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