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




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

本帖最后由 jim9 于 2011-8-28 06:46 编辑
2 T8 U( e2 g: `6 w+ z% [, F: D$ h
我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
! k: }: _# `4 B2 h$ }' m8 ?Example 1. % t5 V3 T7 }$ r+ {+ R# K  M' H3 D. M4 I
----------------------------
, R* g7 r5 w, w! d! x$ h: M----------------------------
$ J) Z/ \/ T7 G9 k! L' b2 nob_start(); //打开缓冲区 ( I7 _1 `- }3 t2 q, I( E
echo "Hello\n"; //输出
/ @( n/ u* j; {header(“location:index.php”); //把浏览器重定向到index.php
1 @, Y+ u- O; P; \3 uob_end_flush();//输出全部内容到浏览器
, _$ |2 ~- I% F' [?>
% L- |2 c5 m6 P3 Y----------------------- 3 E3 k* E* ], \6 O: P
----------------------- & y. c) h! h3 T% Z6 g
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用 / p5 ?: L- F% p+ @2 q$ A' O. P) ~* F/ R
这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我
: n7 \4 c$ p+ |# K  K4 A; p2 T们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:“Header had : m4 X3 H$ h) g8 R. C
all ready send by”!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
: Q# y* Z- A# `9 r
  c" f$ u6 S# w, k一、 相关函数简介:
& l3 d7 ^0 y8 W+ h/ l# S* V1、Flush:刷新缓冲区的内容,输出。 5 E: s# \8 n% Q& T' k: d1 ^
函数格式:flush()
! C( O$ D' H4 e4 ]  i& u) v说明:这个函数经常使用,效率很高。
1 e/ ?% T5 |& G% H0 Y$ [* A; n2、ob_start :打开输出缓冲区 4 R4 A% v  h. ?8 a
函数格式:void ob_start(void) 5 P9 R! ]8 Z" j, h" X
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。
' b# B1 G# B% P, r5 v8 J% H1 t为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
1 x$ R- g9 U, H3 u; K% C3 、ob_get_contents :返回内部缓冲区的内容。
1 \9 N2 q7 Q) M5 u4 k5 c" `使用方法:string ob_get_contents(void) % z* s* D$ H6 Z( \6 e7 @% L
说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
0 X" ?! [, |# W1 m# I4、ob_get_length:返回内部缓冲区的长度。
) F/ S  F5 i/ s* v) u5 m使用方法:int ob_get_length(void)
. L( l# d- K+ G$ L9 c# q说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激 ( x. [, D# c  H* Y! T6 T  _
活。则返回 FALSE。
; z& G7 l& s) ?4 a; P% b/ Q/ S5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
$ `" N1 b' @' n5 H, i; A使用方法:void ob_end_flush(void) / [! \  T( H, Z4 [& D/ d
说明:这个函数发送输出缓冲区的内容(如果有的话)。
4 P$ H; c1 Y9 k6 L# \. W) A$ M. [* l6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区 + T/ f* s, t, Q7 A; H5 @0 w7 Q5 G4 |
使用方法:void ob_end_clean(void) # P* [) w* M. N" s$ S2 H( [* |
说明:这个函数不会输出内部缓冲区的内容而是把它删除! 6 `( D3 E) y4 E
7、ob_implicit_flush:打开或关闭绝对刷新 * k2 |! z, ^- F5 I0 |6 B% h) K
使用方法:void ob_implicit_flush ([int flag])
: r. e3 q- S1 W, v. F9 j4 Y说明:使用过Perl的人都知道=x的意义,这个字符串可以打开/关闭缓冲区,而 " r+ c( Y$ b) Y9 z  ?
ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直 # F: O, D3 K2 I/ ]
接发送到浏览器,不再需要调用 flush()
9 d8 J" ]+ ]& k2 z" }9 u0 G) {9 v) u
二、深入了解:
* S/ q3 L4 s2 u. c! @) ^5 l1. 关于Flush函数:
1 @/ E  L, g! L2 e这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser
. E9 \+ m5 _: f& R+ y的cache.我们举一个运行效果非常明显的例子来说明flush.
$ }3 w% F- n; B$ ^Example 2.
  `+ G: N7 G2 R$ C+ _---------------------------------
% R+ j! K  ^, s7 c$ e2 K--------------------------------- . |8 b$ r7 G8 F" \
for( = 1; <= 300; ++ ) print(“ “);
* M$ o" h, q( X- D$ `// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
' u/ f; d$ d! d" l) ?5 X; ~// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经 2 E) X# c  s+ G7 V' s+ X6 g# p# t
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
0 l" f  M2 j9 h8 N/ z9 {: U// 源源不断的被发送出去。 4 l7 [( N1 T6 K8 g; h# c, q
For( = 1; <= 20; ++) { + R/ F2 f% @2 f$ c
echo .”
& ?3 n! \, V& H1 A6 T”; " F0 t5 A3 q' |0 }- m2 M8 K
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上 ! G  a3 L( k. \6 D: i6 d. ~/ `
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚 & n; f6 X- n, }; _' ]" c
}
4 |4 ^. w+ t& t9 Q' S% ~?>   ~9 R2 D2 X* P8 Y0 X8 y. Y1 ~
--------------------------------- ( O0 J( k' l8 S3 F, f! p
---------------------------------
* h0 ~0 B! M1 C0 K: ~% C具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php ) n: b7 m' i& q; J
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L
7 }7 P0 ^' Q* D7 [7 L注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush
* C; b8 P( B6 l( I& e* `$ I+ z) ](),这样做的好处是:提高效率!
1 p' s# W- f: I+ |, Y& E2. 关于ob系列函数: + L  z% i/ N% A6 j$ k9 E) G
我想先引用我的好朋友y10k的一个例子:
: r2 G& I9 O. D& C+ g/ xExample 3.
6 B. U' K# |2 y/ f; G$ p1 S---------------------------------
; {5 Y- Q' H1 g: X---------------------------------
- `, l  r5 I  g; b比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要
, z2 m( c. J/ b. A& A, v" g保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了 9 y9 l8 h6 K7 o8 v
缓冲区的控制,我们可以轻松的解决: % h6 Q, e! k7 n/ R9 x% s- ?
---------------------------- : P8 w0 K. M/ M6 s; e
ob_start(); //打开缓冲区
2 Z' k. }% M) Y0 }$ iphpinfo(); //使用phpinfo函数 ; a" V. z' J3 `' h2 f' C
=ob_get_contents(); //得到缓冲区的内容并且赋值给 ) R8 A* w4 A: A) T* n6 W0 H/ K
=fopen('info.txt','w'); //打开文件info.txt
; e, f( w* O* b% lfwrite(,); //写入信息到info.txt ' j/ \# K0 w  w+ Q# M3 x, `
fclose(); //关闭文件info.txt ( c! V8 v$ I) {1 O8 Z8 r
?> # K( }3 S( }5 t! ~: ^
------------------------- $ K* M, e6 |$ w( f- j4 v& }! E
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上
9 _/ W) @0 Y" f: Y! V7 [  N面就是将一些“过程”转化为“函数”的方法!
! C+ J1 E$ n' ]0 A$ w2 c2 I& i' ?
或许有人会问:“难道就这个样子吗?还有没有其他用途?”当然有了,比如笔者论坛的PHP 语
2 a+ Y; f4 Z/ M! ?, P- n5 u- D法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次 & X! \8 j  d' o- T3 f( w
调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留   Z) {6 [. z1 K' {- p
了),大家如果感兴趣的话可以来看看http://bbs.fjbjdd.com/
6 B6 y$ T8 T5 }. V! Z, B------------------------------- # i# V3 t1 f  ]5 q
-------------------------------
6 o% O9 g  R4 V  i可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌 $ B9 e" N% S$ v( R" J
握了使用ob_start()的要点。
. M: {9 Y3 c$ w9 W# M, x<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush
5 a2 P% x% S4 u4 C7 e) I(),ob_end_flush()(或程序执行完毕)之前不会被输出。 ( }  m0 n$ [  M- l8 E0 M
<2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及
. u$ {" Q5 |5 f, e9 Q* a4 u8 esession,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后
' c& B& ]) k7 x8 x9 U自动运行命令,比如ob_start("ob_gzhandler");而我们最常用的做法是用ob_get_contents()得
2 s  Z6 [( I! E6 w到cache中的内容,然后再进行处理…… $ `9 g, _4 Z( I; d
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完
) j' c' \, k1 m& b) _2 o毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。 : R, }: R. s+ ~/ E
来,让我们看看能用ob系列函数做些什么…… $ `$ w/ x- d% w" ~/ e5 e
一、 静态模版技术 4 m4 X" m3 m5 ?0 T/ k
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页
4 {+ e8 R- D) e9 d% z2 e, Z3 q. L面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用
4 |5 k' K+ W$ D% @' o+ v2 GPHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带
: n$ M1 d4 X4 K6 U# u; e来的好处是非常巨大的。 6 X  \( l0 q; W" m+ |
我所知道的实现静态输出的有两种办法:
3 @" `7 |7 {8 _0 t3 J<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。 4 l, [: ^* x7 G
<2>.使用ob系列函数实现。
7 B8 \2 _6 C- r+ V' [/ f5 z1 E" u对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。   [  Z( [5 K' J+ N/ n' X
我们现在来看一看第二种方法的具体实现:
, i3 ^& w) @6 i: ]) fExample 4.
5 h0 l. ^( ]9 c) `, t- I---------------------------------
5 y2 W% L, a5 d- J0 J---------------------------------
8 u6 z6 s$ `* Vob_start();//打开缓冲区
- d& z+ y) |+ V$ u: {7 p; ]?> ' @* _7 M8 {! {
php页面的全部输出 4 J* K& ^! \2 w* H6 f
= ob_get_contents();//取得php页面输出的全部内容
% i2 u+ R$ q% O( t= fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
6 m% I; m& I5 p, K# Bfwrite(, ); //把php页面的内容全部写入output00001.html,然后……   F% N" ^4 @/ f5 q( s
fclose();
1 Q+ }5 y7 g" n( x?> - }- V, `; r" n
---------------------------------
3 p* V7 X# ?2 }4 r3 w' J--------------------------------- : O" D7 s% A. G( z
这样,所谓的静态模版就很容易的被实现了…… ( f  r& {! a/ U2 q) L7 C: Q
二、 捕捉输出   `' G! u8 u# w, \5 g0 |
以上的Example 4.是一种最简单的情况,你还可以在写入前对
. i7 V2 [, @: j你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。
+ ]6 O5 v) l: c4 N个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的
; G" y* H7 B  ~6 d想象力……
+ l% u8 }1 A0 s1 b+ X  ^, wExample 5.
( r4 |9 b( m9 x5 o+ |# Q1 E% y---------------------------------
2 @% y6 s% [( W' Z( c1 M--------------------------------- % j+ ?, U6 F6 H0 d" K1 D
Function run_code() {
& k; b0 u0 E; t/ K& GIf() {
2 n5 D/ @8 J7 t0 z* q6 Qob_start(); / ^3 I1 e4 m! z& i
eval(); ' h3 c6 Z2 n+ `! S# S  |, t, c
= ob_get_contents(); 3 l9 F& ~- N5 e  \% r  A' {/ t0 V! r
ob_end_clean();
% U. b5 [) G' U5 U6 D}else {
. N' A1 d" q6 t' a; a$ R0 ?echo “错误!没有输出”;
7 U" v9 x1 h( m' q! M& z0 J6 lexit();
, ?' }: Z$ S9 O' [& D} . F# j* ?, N- p/ `' c; D9 u
return ;
* _% P# L0 e$ y' T& k7 m1 [$ N}
3 Q5 [" e! i( N, `9 c-------------------------------- % _- s# f: R6 x0 D
--------------------------------- 1 ]& i+ R" k1 G. L
以上这个例子的用途不是很大,不过很典型 ) f& a& P' H# S. O+ _" ^
子用eval把
6 G7 X9 z4 ?* N9 O7 O9 |9 dExample 6. 加快传输
; v/ Z2 w' @6 ~$ \2 f--------------------------------- 4 K$ P0 b7 x6 `
---------------------------------
4 C5 Q) p4 q0 M6 T: Z# Y4 _& V/*
9 u. d: i" Z) h) T  H1 Q** Title.........: PHP4 HTTP Compression Speeds up the Web
- t( L, z( K- s** Version.......: 1.20 ! I, G& f4 G1 A  S0 o  n
** Author........: catoc & E3 |% N; `7 f$ v* d
** Filename......: gzdoc.php $ z* ^! A9 ~' K/ o
** Last changed..: 18/10/2000 ; A' K' ~$ p) I/ j' R
** Requirments...: PHP4 >= 4.0.1 % [; s( C' e6 z1 _% J( i
** PHP was configured with --with-zlib[=DIR] / H1 A" K9 W! e5 Y
** Notes.........: Dynamic Content Acceleration compresses
4 b9 K0 S) x2 H% D** the data transmission data on the fly 0 ^; p/ k# _' ~, d/ `1 G5 n
** code by sun jin hu (catoc)
) E. A& O, a. x; {* `5 [** Most newer browsers since 1998/1999 have 3 X, [  y( N" E) k5 }
** been equipped to support the HTTP 1.1
: o. {6 N4 E+ ?7 ?  _+ B  k** standard known as "content-encoding." 1 o$ q  E+ Z) k7 h& A/ v
** Essentially the browser indicates to the : `8 I1 I! x# E4 r! K) k6 \/ ^
** server that it can accept "content encoding" ; {8 z" W4 A+ z: i/ V1 [
** and if the server is capable it will then 7 q4 O) x% F- `: {; h7 r5 F% w
** compress the data and transmit it. The 1 q, a' b8 K' I' p* p" W1 ?
** browser decompresses it and then renders 7 F! t( r0 T/ e$ ]6 m% @
** the page. % f% N" Z2 Y1 @( r, m8 X1 x! s
** 4 Q$ \# `( ?9 Z8 P( i5 \
** Modified by John Lim (jlim@natsoft.com.my)
. h. T2 d. v+ q** based on ideas by Sandy McArthur, Jr 3 B& K  [4 g7 r6 }: O! h! v
** Usage........: 0 n) t7 [+ N' v
** No space before the beginning of the first ' ** ------------Start of file---------
  A, P2 J+ k/ m/ t-
  j, R/ B2 w4 u" T$ @** │ ** │ include('gzdoc.php');
0 G3 s$ @! J  H2 O3 b$ ~7 S# D** │? > , V$ v% @! d' V" ~6 L/ _0 X0 y
** │
1 K  i! }1 {9 t! P- s) I$ A( M& s** │... the page ... 3 q- O2 P% C( X$ w1 u. ?
** │
7 T4 t( [! U) j2 t( P1 n; v1 m: u2 n; E** │ ** │ gzdocout(); # T; w, `  R" w7 U2 m
** │? >
8 u+ t: f$ u7 {0 `1 y) I, i. h' O' i** -------------End of file-----------
0 `7 W% Z9 N9 y* N) v*/ ' j  m/ v0 b& G
ob_start();
! k/ c4 X3 A% R: j- V  Gob_implicit_flush(0);
) k+ B: L$ M& u* N5 lfunction CheckCanGzip(){ ' j4 d( n  u; ]) a/ W0 U0 U5 e# x
global ;
' j: K) I& P; s3 P1 Uif (headers_sent() ││ connection_timeout() ││ connection_aborted()){ " o) N% {0 z/ {9 ^. @; d
return 0; ( R1 v/ l# r7 _- G3 \4 e
}
7 z( ~9 R* D- E5 z+ c; e$ \if (strpos(, 'x-gzip') !== false) return "x-gzip"; $ b- E7 T0 k0 r2 f
if (strpos(,'gzip') !== false) return "gzip"; & v' h6 O7 m% U0 L4 ?* f% F
return 0; 0 z' n# y  ~' P- h  t4 u
}
0 S1 G* r. H1 {0 e! H' T2 @& s1 ^/* = compression level 0-9, 0=none, 9=max */ ! q# I% E- i) m* h
function GzDocOut(=1,=0){
* T' [8 l& _7 f' k  q= CheckCanGzip();
' a' K. c0 S2 G) Lif (){ $ N0 g4 y* i9 O
print "\n\n"; # t9 z. G0 h) J8 {
= ob_get_contents(); 3 i) `' k7 a+ C9 Y) ?' t
ob_end_clean(); 9 i# H6 C% e- ^: j$ u  _- J
if (){ 5 w( H; z, d( q3 y
= "
, ~' s' q+ x3 t  M5 ^9 ^Not compress length: ".strlen(); 9 n( M& y4 `( k+ o0 Z# r5 \; u( c( {
.= "
' f; N8 I6 T& @; ^  g# M6 }Compressed length: ".strlen(gzcompress(,)); / Y1 s" h! P0 Z- q4 _: a9 X: u+ r
.= ; # e3 m) }3 `7 g1 U5 L
} ; i2 c4 ?" Z" {5 V
header("Content-Encoding: ");   J6 N, J7 S7 z  t
print "\x1f\x8b\x08\x00\x00\x00\x00\x00";   H, U6 K' t9 h. K0 m3 O
= strlen(); - H+ K+ T8 e4 ]0 V. W
= crc32(); $ i7 Z  o. ~% B+ D/ K  ?2 h6 ^6 l
= gzcompress(,); , S0 l" ~8 b7 x! R/ J
= substr(, 0, strlen() - 4); : G8 ]2 f0 p! x( ~$ h" j( A
print ;
' g9 }' @; m0 X) M% G# V/ Aprint pack('V',);
0 r6 ~# N! y% c0 h+ Gprint pack('V',); . D: W1 i( D3 }: |
exit; 3 c% `# t1 n! b3 J$ `  k
}else{
: w2 I1 X: c4 H; e. {, Fob_end_flush(); 1 v: Z; y" W1 O! m* z0 {
exit;
* @" S) n6 n1 N} # K, I! i# l9 X0 W  _
} 7 q% d) S3 E2 k+ f
?> 9 v- a' y$ j: Z! G" f1 `8 z
------------------------------------------------------------------------------------- 3 y1 T; z" J" i' y& u
--------------------------------- 4 e7 t% p2 W2 g: x% p* D
这是catoc的一段很早以前的代码,是在http://weblogs.com 看到的,他利用了zlib的函数,对传输的内 $ s0 q  \( C5 K2 p0 j5 i. B. x
容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显……) C; V$ N; I. n8 b; g0 N! T7 m6 w& O
5 Q& v$ _+ }, ?" y' I; H
参考: http://hi.baidu.com/szsafe/blog/item/9a0ac01f7c368511304e1592.html

也是支持,我代表大家顶你了% a* I; P7 K9 ^+ C

3 O" }  v) D1 u% N; Q% u$ u, t, [! ]" L+ @1 {2 ^: |% C) k" U" ^8 H
$ O  c0 F! u7 c( M" H
. `; Z* a2 ~3 t$ k
* c/ u3 v5 K2 ^7 p( P

( r6 N. H6 S1 G' c+ r5 H. |3 V  O/ G/ q2 h0 ]$ |8 I

1 A4 z% B, W* \% P3 F% s* x- S
; Q8 S" q, ?- `6 o
$ N. C1 l$ R* L5 X/ V- I2 a+ L" m# j- J; N; f7 Q" ?; L% O  j

8 Z& W7 }* h: l8 r3 Nmaiwenping.org


TOP

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