ob_start()
是否用于 output buffering
以使标头被缓冲而不发送到浏览器?我在这里有意义吗?如果不是,那我们为什么要使用 ob_start()
?
将 ob_start()
想象为“开始记住通常会输出的所有内容,但还没有对它做任何事情。”
例如:
ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();
您通常将其与其他两个函数配对:ob_get_contents()
,它基本上为您提供自从使用 ob_start()
打开缓冲区以来“保存”到缓冲区的任何内容,然后是 ob_end_clean()
或 ob_flush()
,它们可以是分别停止保存并丢弃已保存的内容,或停止保存并立即输出所有内容。
我使用它,所以我可以用大量 HTML 打破 PHP 但不渲染它。它使我免于将其存储为禁用 IDE 颜色编码的字符串。
<?php
ob_start();
?>
<div>
<span>text</span>
<a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>
代替:
<?php
$content = '<div>
<span>text</span>
<a href="#">link</a>
</div>';
?>
ob_get_clean()
,而不是 ob_end_clean()
此处接受的答案描述了 ob_start()
的作用 - 而不是使用它的原因(这是提出的问题)。
如其他地方所述,ob_start()
创建了一个缓冲区,输出被写入其中。
但是没有人提到可以在 PHP 中堆叠多个缓冲区。请参阅 ob_get_level()。
至于为什么......
以更大的块向浏览器发送 HTML 可以从减少网络开销中获得性能优势。以较大的块将数据从 PHP 中传递出来,通过减少所需的上下文切换的数量来提供性能和容量优势 将较大的数据块传递到 mod_gzip/mod_deflate 提供了性能优势,因为压缩可以更有效。缓冲输出意味着您仍然可以稍后在代码中操作 HTTP 标头 在输出 [head]....[/head] 后显式刷新缓冲区可以允许浏览器在 HTML 流完成之前开始为页面编组其他资源.在缓冲区中捕获输出意味着它可以重定向到其他功能,例如电子邮件,或复制到文件作为内容的缓存表示
output_buffering = 200000
。在某些情况下(但不是全部),可以在 .htaccess 文件中完成此类启用,例如:php_value output_buffering 200000
。
你倒过来了。 ob_start 不缓冲标题,它缓冲内容。使用 ob_start
允许您将内容保存在服务器端缓冲区中,直到您准备好显示它。
这通常用于使页面可以在它们已经“发送”一些内容之后发送标题(即,决定在呈现页面的中途重定向)。
我更喜欢:
ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
这是为了进一步澄清JD Isaaks answer ...
您经常遇到的问题是您使用 php 从许多不同的 php 源输出 html,而这些源通常,无论出于何种原因,通过不同的方式输出。
有时你有想要直接输出到浏览器的文字 html 内容;其他时候,输出是动态创建的(服务器端)。
动态内容总是(?)将是一个字符串。现在,您必须将这个字符串化的动态 html 与任何文字、直接显示的 html ... 组合成一个有意义的 html 节点结构。
这通常会迫使开发人员将所有直接显示的内容包装成一个字符串(正如 JD Isaak 所讨论的那样),以便它可以与动态 html 一起正确交付/插入......即使你真的没有想把它包起来。
但是通过使用 ob_## 方法,您可以避免字符串包装的混乱。相反,文字内容输出到缓冲区。然后在一个简单的步骤中,将缓冲区的全部内容(所有文字 html)连接到您的动态 html 字符串中。
(我的示例显示将文字 html 输出到缓冲区,然后将其添加到 html-string 中……另请参阅 JD Isaaks 示例以查看 string-wrapping-of-html)。
<?php // parent.php
//---------------------------------
$lvs_html = "" ;
$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__without_ob( ) ;
$lvs_html .= "<div>more html</div>" ;
$lvs_html .= "----<br/>" ;
$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__with_ob( ) ;
$lvs_html .= "<div>more html</div>" ;
echo $lvs_html ;
// 02 - component contents
// html
// 01 - component header
// 03 - component footer
// more html
// ----
// html
// 01 - component header
// 02 - component contents
// 03 - component footer
// more html
//---------------------------------
function gf_component_assembler__without_ob( )
{
$lvs_html = "<div>01 - component header</div>" ; // <table ><tr>" ;
include( "component_contents.php" ) ;
$lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;
return $lvs_html ;
} ;
//---------------------------------
function gf_component_assembler__with_ob( )
{
$lvs_html = "<div>01 - component header</div>" ; // <table ><tr>" ;
ob_start();
include( "component_contents.php" ) ;
$lvs_html .= ob_get_clean();
$lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;
return $lvs_html ;
} ;
//---------------------------------
?>
<!-- component_contents.php -->
<div>
02 - component contents
</div>
现有答案中未提及以下内容:缓冲区大小配置 HTTP 标头和嵌套。
ob_start 的缓冲区大小配置:
ob_start(null, 4096); // Once the buffer size exceeds 4096 bytes, PHP automatically executes flush, ie. the buffer is emptied and sent out.
上面的代码提高了服务器性能,因为 PHP 将发送更大的数据块,例如 4KB(没有 ob_start 调用,php 会将每个回显发送到浏览器)。
如果您在没有块大小的情况下开始缓冲(即简单的 ob_start()),那么页面将在脚本结束时发送一次。
输出缓冲不影响 HTTP 标头,它们以不同的方式处理。但是,由于缓冲,即使在发送输出后您也可以发送标头,因为它仍在缓冲区中。
ob_start(); // turns on output buffering
$foo->bar(); // all output goes only to buffer
ob_clean(); // delete the contents of the buffer, but remains buffering active
$foo->render(); // output goes to buffer
ob_flush(); // send buffer output
$none = ob_get_contents(); // buffer content is now an empty string
ob_end_clean(); // turn off output buffering
在这里很好地解释了:https://phpfashion.com/everything-about-output-buffering-in-php
此功能不仅适用于标题。你可以用它做很多有趣的事情。示例:您可以将页面拆分为多个部分并像这样使用它:
$someTemplate->selectSection('header');
echo 'This is the header.';
$someTemplate->selectSection('content');
echo 'This is some content.';
您可以捕获此处生成的输出并将其添加到布局中两个完全不同的位置。
不,你错了,但方向适合;)
输出缓冲缓冲脚本的输出。这就是(简而言之)echo
或 print
之后的内容。带有标头的事情是,如果它们尚未发送,它们只能被发送。但是 HTTP 说,标头是传输的第一个。因此,如果您第一次(在请求中)输出某些内容,则会发送标头,并且您不能设置任何其他标头。
不定期副业成功案例分享
ob_get_contents()
替换为ob_get_clean()
并删除ob_end_clean()
,因为ob_get_clean()
本质上执行这两个功能。参考:php.net/manual/en/function.ob-get-clean.php(PHP 4 >= 4.3.0,PHP 5)ob_start();
这是正确的吗?如果未启用会怎样?ob_end_clean
修复我的代码后,它就像一个魅力!谢谢@Riley Dutton