百科狗-知识改变命运!
--

ob_start() - php 输出缓冲函数

梵高1年前 (2023-11-21)阅读数 21#技术干货
文章标签函数

ob_start()

(PHP 4, PHP 5, PHP 7)

打开输出控制缓冲

说明

ob_start([callback$output_callback[,int $chunk_size[,bool $erase]]]): bool

此函数将打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(除http标头外),相反需要输出的内容被存储在内部缓冲区中。

内部缓冲区的内容可以用ob_get_contents()函数复制到一个字符串变量中。想要输出存储在内部缓冲区中的内容,可以使用ob_end_flush()函数。另外,使用ob_end_clean()函数会静默丢弃掉缓冲区的内容。

Warning

当有正在调用的回调函数时,一些网络服务器(例如Apache)会改变一个脚本的工作目录。你可以在回调函数中再把它改回来,例如chdir(dirname($_SERVER['SCRIPT_FILENAME']))

输出缓冲区是可堆叠的,这即意谓着,当有一个ob_start()是活跃的时,你可以调用另一个ob_start()。只要确保又正确调用了ob_end_flush()恰当的次数即可。如果有多重输出回调函数是活跃的,输出内容会一直按嵌套的顺序依次通过它们而被过滤。

参数

$output_callback

可选参数$output_callback函数可以被指定。此函数把一个字符串当作参数并返回一个字符串。当输出缓冲区被(ob_flush(),ob_clean()或者相似的函数)冲刷(送出)或者被清洗的时候;或者在请求结束之际输出缓冲区内容被冲刷到浏览器的时候该函数将会被调用。当调用$output_callback时,它将收到输出缓冲区的内容作为参数并预期返回一个新的输出缓冲区作为结果,这个新返回的输出缓冲区内容将被送到浏览器。如果这个$output_callback不是一个可以调用的函数,此函数会返回FALSE

如果回调函数有两个参数,第二个参数会由一个位域补充,该位域由PHP_OUTPUT_HANDLER_START,PHP_OUTPUT_HANDLER_CONTPHP_OUTPUT_HANDLER_END组成。

ob_start() - php 输出缓冲函数

如果$output_callback返回FALSE,其原来的输入内容被直接送到浏览器。

这个参数$output_callback可以通过直接给一个NULL值而避开。

ob_end_clean(),ob_end_flush(),ob_clean(),ob_flush()andob_start()不能从一个回调函数中调用。如果从回调函数中调用了它们,产生的行为是不明确的。如果想要删除缓冲区的内容,从回调函数中返回一个""(空字符串)。更不能从一个回调函数中使用像print_r($expression, true)highlight_file($filename, true)一样的输出缓冲函数。

Note:

在PHP 4.0.4中,ob_gzhandler()被引入是为了简化把gz编码过数据发送到支持压缩网页的浏览器。ob_gzhandler()会判定浏览器可以接受哪种类型的编码内容,并返回相应的输出。$chunk_size

如果可选参数$chunk_size被赋值了,在任何一个能引起缓冲区的长度等于或超过$chunk_size的输出操作后,缓冲区都会被刷送。默认值 0 意味着函数仅在最后被调用,其余的特殊值可以将$chunk_size从 1 设定到 4096。

$erase

如果可选参数$erase被赋成FALSE,直到脚本执行完成缓冲区才被删除。这使得,如果调用了冲刷和清洗(清除)函数,会抛出一个“notice”,并返回FALSE值。

返回值

成功时返回TRUE,或者在失败时返回FALSE

更新日志

版本说明
4.3.2在传递的$output_callback不能被执行时,此函数被改成返回FALSE
4.2.0添加了$erase参数。

范例

用户自定义回调函数的例子

It's like comparing apples to oranges.

以上例程会输出:

It's like comparing oranges to oranges.

参见

  • ob_get_contents() 返回输出缓冲区的内容
  • ob_end_clean() 清空(擦除)缓冲区并关闭输出缓冲
  • ob_end_flush() 冲刷出(送出)输出缓冲区内容并关闭缓冲
  • ob_implicit_flush() 打开/关闭绝对刷送
  • ob_gzhandler() 在ob_start中使用的用来压缩输出缓冲区中内容的回调函数。ob_start callback function to gzip output buffer
  • ob_iconv_handler() 以输出缓冲处理程序转换字符编码
  • mb_output_handler() 在输出缓冲中转换字符编码的回调函数
  • ob_tidyhandler()ob_start callback function to repair the buffer
The following should be added: "If outbut buffering is still active when the script ends, PHP outputs it automatically. In effect, every script ends with ob_end_flush()."
You can use PHP to generate a static HTML page. Useful if you have a complex script that, for performance reasons, you do not want site visitors to run repeatedly on demand. A "cron" job can execute the PHP script to create the HTML page. For example: 
If you're using Apache (1.3x or 2.0), you might consider adding automatic compression capability to your delivered pages.
I assume you all know how to build compression classes and use them in your programs, but none has yet to offer the speed and robustness of a binary-compiled module. Furthermore, such modules also log the "compressable" hit in the web log file, thus allowing your favorite web anaysing program to show you reports of bandwidth saved.
Having said that, you might consider the following two modules for Apache:
1) Apache 1.3x: use mod_gzip, available from:
http://sourceforge.net/projects/mod-gzip/
2) Apache 2.x: use mod_gz, see here:
http://www.mail-archive.com/dev@httpd.apache.org/msg00734.html
3) Apache 1.3x: you may also want to use mod_defalte, from:
ftp://ftp.lexa.ru/pub/apache-rus/contrib/
Hope it helps.
If you're using object-orientated code in PHP you may, like me, want to use a call-back function that is inside an object (i.e. a class function). In this case you send ob_start a two-element array as its single argument. The first element is the name of the object (without the $ at the start), and the second is the function to call. So to use a function 'indent' in an object called '$template' you would use .
When you rely on URL rewriting to pass the PHP session ID you should be careful with ob_get_contents(), as this might disable URL rewriting completely.
Example:
ob_start();
session_start();
echo 'self link';
$data = ob_get_contents();
ob_end_clean();
echo $data;
In the example above, URL rewriting will never occur. In fact, rewriting would occur if you ended the buffering envelope using ob_end_flush(). It seems to me that rewriting occurs in the very same buffering envelope where the session gets started, not at the final output stage.
If you need a scenario like the one above, using an "inner envelope" will help:
ob_start();
ob_start();  // add the inner buffering envelope
session_start();
echo 'self link';
ob_end_flush(); // closing the inner envelope will activate URL rewriting
$data = ob_get_contents();
ob_end_clean();
echo $data;
In case you're interested or believe like me that this is rather a design flaw instead of a feature, please visit bug #35933 (http://bugs.php.net/bug.php?id=35933) and comment on it.
When a script ends, all buffered output is flushed (this is not a bug: http://bugs.php.net/bug.php?id=42334&thanks=4). What happens when the script throws an error (and thus ends) in the middle of an output buffer? The script spits out everything in the buffer before printing the error!
Here is the simplest solution I have been able to find. Put it at the beginning of the error handling function to clear all buffered data and print only the error:
$handlers = ob_list_handlers();
while ( ! empty($handlers) )  {
  ob_end_clean();
  $handlers = ob_list_handlers();
}
Some web hosting servers (mine do, at least) have in their php.ini the following setting:
output_handler = ob_gzhandler
This proved problematic for php-scripts which returns an image or a binary file in general, since there is no way to determine the content length of the compressed file.
Since I spent a lot of time scouring the net searching for a work-around (.htaccess-modifications were out of the picture for various reasons), I found this to work nicely to cancel out the ob_gzhandler specified in the php.ini:

Put this at the top of the script before anything else is written to the page, and the script result will not be compressed.
Just a word of warning to those like myself who are upgrading from 5.3. I have a piece of code that used to work:

Which is not working anymore (I get an error like: Warning: ob_start(): function '' not found or invalid function name).
It's easily fixed though, just changed the '' to a null, like this:

Which preserves the code intention but works :)
Output Buffering even works in nested scopes or might be applied in recursive structures... thought this might save someone a little time guessing and testing :)
... at least works on Apache 1.3.28
Nandor =)
When using a callback with ob_start(), functions like ob_get_contents() don't make use of it, use ob_end_flush() instead.
nb: not tested with every ob_* functions, just ob_get_contents() and ob_end_flush()
Careful with while using functions that change headers of a page; that change will not be undone when ending output buffering.
If you for instance have a class that generates an image and sets the appropriate headers, they will still be in place after the end of ob.
For instance:

will put the image bytes into $pngString, and set the content type to image/png. Though the image will not be sent to the client, the png header is still in place; if you do html output here, the browser will most likely display "image error, cannot be viewed", at least firefox does.
You need to set the correct image type (text/html) manually in this case.
There is no start flag problem. One just has to notice that the second parameter is not a mode but consists of bitwise-OR'ed flags.

flush
flush 2
flush 3
end flush
0: PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_CONT (3): flush
1: PHP_OUTPUT_HANDLER_CONT (2): flush 2
2: PHP_OUTPUT_HANDLER_CONT (2): clean
3: PHP_OUTPUT_HANDLER_CONT (2): flush 3
4: PHP_OUTPUT_HANDLER_END (4): end flush
Make sure the editor you use does not add the UTF8/UTF16 BOM at the start of the scripts if you want to use ob_start("ob_gzhandler"); 
If those three characters are present, browsers like Firefox won't be able to decode the pages and will report:
Content Encoding Error
The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
Google Chrome will simply report "Error 2 (net::ERR_FAILED): Unknown error."
With the ob_start command commented out, the page is successfully load and the browser will usually detect the BOM and not show it on the page, so everything's hard to debug.
I think it's worth noting that while you can't call any output functions such as echo or print from within a callback function, you can still send headers (presumably including cookies, haven't checked). Of course this only works in the first callback, like so:

Not the most inspiring example, but in this case the code is able to sneak a last-minute header in before the headers part of the response is sent. This can be handy if you want to avoid replacing header values that are uncertain.
For example if your code may return an image, but you don't want to set content type until you're sure that the image can be sent successfully, you can use the callback to leave the decision right until the very last moment, by which point you're hopefully sure of what's being sent in the HTTP body.
In case you're in for some readable representation for flags, this is a variant as a private class member: 
Following clement dot ayme at st dot com 's remark :
In my experience it seems that the output IS buffered, but ALSO sent to the standard output !
In extension to the compress() function posted below, here's a nifty little class that improves the idea a bit. Basically, running that compress() function for all your CSS for every single page load is clearly far less than optimal, especially since the styles will change only infrequently at the very worst. 
With this class you can simply specify an array of your CSS file names and call dump_style(). The contents of each file are saved in compress()'d form in a cache file that is only recreated when the corresponding source CSS changes.
It's intended for PHP5, but will work identically if you just un-OOP everything and possibly define file_put_contents. 
Enjoy! 
Hello firends
ob_start() opens a buffer in which all output is stored. So every time you do an echo, the output of that is added to the buffer. When the script finishes running, or you call ob_flush(), that stored output is sent to the browser (and gzipped first if you use ob_gzhandler, which means it downloads faster). 
The most common reason to use ob_start is as a way to collect data that would otherwise be sent to the browser.
These are two usages of ob_start():
1-Well, you have more control over the output. Trivial example: say you want to show the user an error message, but the script has already sent some HTML to the browser. It'll look ugly, with a half-rendered page and then an error message. Using the output buffering functions, you can simply delete the buffer and sebuffer and send only the error message, which means it looks all nice and neat buffer and send 
2-The reason output buffering was invented was to create a seamless transfer, from: php engine -> apache -> operating system -> web user
If you make sure each of those use the same buffer size, the system will use less writes, use less system resources and be able to handle more traffic. 
With Regards, Hossein
If ob_start does not seem to be working for you, note that with Apache 2 the flush() function causes PHP to send headers regardless of whether ob_start had been called before flush.
ob_start();
echo 'test';
flush();
will cause Apache 2 to send whatever headers may be stacked up - which means you can't use a header(location:xxx) after the flush. To fix, remove the flush(). Spent several hours discovering this. Apache 1.x didn't work this way.
When a fatal error is thrown, PHP will output the current buffer of Output-Control without postprocessing before printing the error message. If you are working with several output control levels, this might not result in the desired behavior.
You can use an output callback handler to handle this and discard the output.
Therefore, use ob_start("ob_error_handler") in connection with the following:
function ob_error_handler($str) {
  $error = error_get_last();
  if ($error && $error["type"] == E_USER_ERROR || $error["type"] == E_ERROR) {
    return ini_get("error_prepend_string").
     "\nFatal error: $error[message] in $error[file] on line $error[line]\n".
     ini_get("error_append_string");
  }
  return $str;
}
Referring to dan at roteloftet dot com's comment:
RFC 2616 (HTTP) specifies a "transparent" Content-Encoding, "identity" (§ 3.5), that nicely suits what you tried to do with the (invalid) "None". So this equally working, and it's also RFC-compliant: 
Way to make all stdout and stderr write to a log
from *inside* a php script.
You simply need to make sure to call elog() every
once in awhile to get output.
It's a nice way to "daemonize" a script w.r.t. its logging.
// This allows us to capture all stdout and stderr (and error_log() calls)
// to this logfile...
// The "collected output" will be flushed anytime "elog()" is used...
ini_set("error_log", "/var/log/script.log");
ob_start();
function elog($str)
{
 // get anything written to stdout or stderr that did *NOT* use elog()
 // and write it now...
 $writeme = ob_get_contents();
 if ($writeme)
 {
  error_log($writeme);
  ob_end_clean();
  ob_start();
 }
 // now write message this method was called with
 error_log($str);
}
With ob callback: note that the second parameter sent to your method won't help you differentiate between flush calls and calls to ob_clean, but the buffer contents is sent in both cases, so you end up parsing data that isn't going to be used. Also, note that the constant PHP_OUTPUT_HANDLER_START is never actually sent, rather the integer "3" turns up on first flush:

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)