在php中使用ob_start()有什么用?

Adi*_*kla 280 php output-buffering

ob_start()用于output buffering使头被缓冲,而不是发送到浏览器?我在这里有道理吗?如果没有那么我们为什么要使用ob_start()

Ril*_*ton 454

想想ob_start()说"开始记住通常会输出的所有内容,但还没有对它做任何事情."

例如:

ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();
Run Code Online (Sandbox Code Playgroud)

通常还有两个其他功能配对:ob_get_contents()它基本上可以为您提供已经"保存"到缓冲区的任何内容,因为它已打开ob_start(),然后ob_end_clean()或者ob_flush(),它会停止保存并丢弃保存的内容,或者停止保存并分别一次输出.

  • 很棒的解释.我会更进一步,用`ob_get_clean()`替换`ob_get_contents()`并删除`ob_end_clean()`,因为`ob_get_clean()`基本上执行这两个函数.参考:http://php.net/manual/en/function.ob-get-clean.php(PHP 4> = 4.3.0,PHP 5) (51认同)
  • @Riley Dutton你没有说明为什么使用ob_start() (5认同)

JD *_*cks 148

我使用这个,所以我可以用很多HTML打破PHP,但不能渲染它.它使我无法将其存储为禁用IDE颜色编码的字符串.

<?php
ob_start();
?>
<div>
    <span>text</span>
    <a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>
Run Code Online (Sandbox Code Playgroud)

代替:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>
Run Code Online (Sandbox Code Playgroud)

  • 没想到这一点,这是一种令人难以置信的IDE开发方式!另外,它消除了我在PHP中将Javascript或HTML作为字符串的需要,不断地逃避"等等,这很烦人 (11认同)

sym*_*ean 80

这里接受的答案描述了什么ob_start()- 不是为什么使用它(这是问题).

如其他地方所述,ob_start()创建一个写入输出的缓冲区.

但是没有人提到可以在PHP中堆叠多个缓冲区.请参见ob_get_level().

至于为什么....

  1. 以较大的块将HTML发送到浏览器可以从减少的网络开销中获得性能优势.

  2. 通过减少所需的上下文切换次数,以较大的块将数据传递出PHP可以提高性能和容量

  3. 将更大的数据块传递给mod_gzip/mod_deflate可以提高性能,因为压缩可以更高效.

  4. 缓冲输出意味着您仍然可以在代码中稍后操作HTTP标头

  5. 在输出[head]后显式刷新缓冲区.... [/ head]可以允许浏览器在HTML流完成之前开始编组页面的其他资源.

  6. 捕获缓冲区中的输出意味着它可以重定向到其他功能,如电子邮件,或作为内容的缓存表示复制到文件


Cra*_*ige 28

你倒退了.ob_start不缓冲标头,它缓冲内容.使用ob_start允许您将内容保留在服务器端缓冲区中,直到您准备好显示它.

这通常用于使页面可以在"已经''已经'发送'一些内容之后发送标题(即,决定通过呈现页面的一半重定向).

  • +1我也对该功能的实际用法感到困惑.您在"重定向"期间使用它的答案让我想起了我已经收到错误"Headers already sent"的所有时间.谢谢 (3认同)

haw*_*awx 13

我更喜欢:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
Run Code Online (Sandbox Code Playgroud)


dsd*_*dsd 8

这是为了进一步澄清JD Isaaks的回答 ......

您经常遇到的问题是您使用php从许多不同的PHP源输出html,并且这些源通常无论出于何种原因通过不同的方式输出.

有时你想要直接输出到浏览器的文字html内容; 其他时候输出是动态创建的(服务器端).

动态内容总是(?)将成为一个字符串.现在你必须将这个字符串化的动态html与任何文字的,直接显示的html ...组合成一个有意义的html节点结构.

这通常会迫使开发人员将所有直接显示内容包装成一个字符串(正如JD Isaak所讨论的那样),这样它就可以与动态html一起正确地传递/插入......即使你不是真的希望它包裹起来.

但是通过使用ob _ ##方法,你可以避免那个字符串包装混乱.相反,文字内容输出到缓冲区.然后在一个简单的步骤中,缓冲区的所有内容(所有文字html)将连接到您的dynamic-html字符串中.

(我的例子显示了将文字html输出到缓冲区,然后将其添加到html-string中......另请参阅JD Isaaks示例以查看字符串包装的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 ;
  } ;

//---------------------------------
?>
Run Code Online (Sandbox Code Playgroud)
<!-- component_contents.php -->
  <div>
    02 - component contents
  </div>
Run Code Online (Sandbox Code Playgroud)


jwu*_*ler 6

此功能不仅仅适用于标题。你可以用它做很多有趣的事情。示例:您可以将页面分成几个部分并像这样使用它:

$someTemplate->selectSection('header');
echo 'This is the header.';

$someTemplate->selectSection('content');
echo 'This is some content.';
Run Code Online (Sandbox Code Playgroud)

您可以捕获此处生成的输出并将其添加到布局中两个完全不同的位置。


sud*_*dip 5

现有答案中未提及以下内容:缓冲区大小配置 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.
Run Code Online (Sandbox Code Playgroud)

上面的代码提高了服务器性能,因为 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
Run Code Online (Sandbox Code Playgroud)

在这里很好地解释:https : //phpfashion.com/everything-about-output-buffering-in-php