php中的ob_start()有什么用?

发布于 2024-10-06 13:18:32 字数 78 浏览 9 评论 0原文

ob_start() 是否用于输出缓冲,以便标头被缓冲而不发送到浏览器?我在这里说得通吗?如果不是,那我们为什么要使用ob_start()呢?

Is ob_start() used for output buffering so that the headers are buffered and not sent to the browser? Am I making sense here? If not then why should we use ob_start()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

枕头说它不想醒 2024-10-13 13:18:32

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(),它要么停止保存并丢弃所有保存的内容,要么停止保存并立即输出所有内容,分别。

Think of ob_start() as saying "Start remembering everything that would normally be outputted, but don't quite do anything with it yet."

For example:

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

There are two other functions you typically pair it with: ob_get_contents(), which basically gives you whatever has been "saved" to the buffer since it was turned on with ob_start(), and then ob_end_clean() or ob_flush(), which either stops saving things and discards whatever was saved, or stops saving and outputs it all at once, respectively.

可遇━不可求 2024-10-13 13:18:32

我使用它,这样我就可以用大量 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>';
?>

I use this so I can break out of PHP with a lot of HTML but not render it. It saves me from storing it as a string which disables IDE color-coding.

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

Instead of:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>
眼藏柔 2024-10-13 13:18:32

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

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

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

至于为什么......

  1. 以较大的块发送 HTML 到浏览器可以通过减少网络开销来提高性能。

  2. 以较大块的形式从 PHP 中传递数据,可以减少所需的上下文切换数量,从而

  3. 将较大的数据块传递到 mod_gzip/mod_deflate 会带来性能优势,因为压缩可以更有效。

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

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

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

The accepted answer here describes what ob_start() does - not why it is used (which was the question asked).

As stated elsewhere ob_start() creates a buffer which output is written to.

But nobody has mentioned that it is possible to stack multiple buffers within PHP. See ob_get_level().

As to the why....

  1. Sending HTML to the browser in larger chunks gives a performance benefit from a reduced network overhead.

  2. Passing the data out of PHP in larger chunks gives a performance and capacity benefit by reducing the number of context switches required

  3. Passing larger chunks of data to mod_gzip/mod_deflate gives a performance benefit in that the compression can be more efficient.

  4. buffering the output means that you can still manipulate the HTTP headers later in the code

  5. explicitly flushing the buffer after outputting the [head]....[/head] can allow the browser to begin marshaling other resources for the page before HTML stream completes.

  6. Capturing the output in a buffer means that it can redirected to other functions such as email, or copied to a file as a cached representation of the content

忆沫 2024-10-13 13:18:32

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

这通常用于使页面可以在已经“发送”一些内容之后发送标头(即,在渲染页面的过程中决定重定向)。

You have it backwards. ob_start does not buffer the headers, it buffers the content. Using ob_start allows you to keep the content in a server-side buffer until you are ready to display it.

This is commonly used to so that pages can send headers 'after' they've 'sent' some content already (ie, deciding to redirect half way through rendering a page).

泪是无色的血 2024-10-13 13:18:32

我更喜欢:

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

I prefer:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer
不打扰别人 2024-10-13 13:18:32

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

您经常遇到的问题是您正在使用 php 输出 html来自许多不同的 php 源,并且这些源通常出于某种原因通过不同的方式输出。

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

动态内容总是(?)是一个字符串。现在,您必须将此字符串化的动态 html 与任何文字、直接显示的 html 结合起来,形成一个有意义的 html 节点结构。

这通常会迫使开发人员将所有直接显示的内容包装到一个字符串中(正如 JD Isaak 所讨论的那样),以便它可以与动态 html 一起正确交付/插入......即使您实际上并不知道想要它包裹起来。

但通过使用 ob_## 方法,您可以避免字符串包装混乱。相反,文字内容会输出到缓冲区。然后,只需一个简单的步骤即可将缓冲区的全部内容(所有文本 html)连接到动态 html 字符串中。

(我的示例显示文本 html 被输出到缓冲区,然后将其添加到 html 字符串中......另请参阅 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>

this is to further clarify JD Isaaks answer ...

The problem you run into often is that you are using php to output html from many different php sources, and those sources are often, for whatever reason, outputting via different ways.

Sometimes you have literal html content that you want to directly output to the browser; other times the output is being dynamically created (server-side).

The dynamic content is always(?) going to be a string. Now you have to combine this stringified dynamic html with any literal, direct-to-display html ... into one meaningful html node structure.

This usually forces the developer to wrap all that direct-to-display content into a string (as JD Isaak was discussing) so that it can be properly delivered/inserted in conjunction with the dynamic html ... even though you don't really want it wrapped.

But by using ob_## methods you can avoid that string-wrapping mess. The literal content is, instead, output to the buffer. Then in one easy step the entire contents of the buffer (all your literal html), is concatenated into your dynamic-html string.

(My example shows literal html being output to the buffer, which is then added to a html-string ... look also at JD Isaaks example to see 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>
只怪假的太真实 2024-10-13 13:18:32

现有答案中未提及以下内容:
缓冲区大小配置
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 -在-php

Following things are not mentioned in the existing answers :
Buffer size configuration
HTTP Header
and Nesting.

Buffer size configuration for 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.

The above code improve server performance as PHP will send bigger chunks of data, for example, 4KB (wihout ob_start call, php will send each echo to the browser).

If you start buffering without the chunk size (ie. a simple ob_start()), then the page will be sent once at the end of the script.

Output buffering does not affect the HTTP headers, they are processed in different way. However, due to buffering you can send the headers even after the output was sent, because it is still in the buffer.

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

Nicely explained here : https://phpfashion.com/everything-about-output-buffering-in-php

合久必婚 2024-10-13 13:18:32

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

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

$someTemplate->selectSection('content');
echo 'This is some content.';

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

This function isn't just for headers. You can do a lot of interesting stuff with this. Example: You could split your page into sections and use it like this:

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

$someTemplate->selectSection('content');
echo 'This is some content.';

You can capture the output that is generated here and add it at two totally different places in your layout.

忆离笙 2024-10-13 13:18:32

不,你错了,但是方向合适;)

输出缓冲缓冲脚本的输出。这就是(简而言之)echoprint 之后的所有内容。标头的问题是,如果尚未发送,则只能发送它们。但 HTTP 规定,标头是传输的第一个部分。因此,如果您第一次(在请求中)输出某些内容,则会发送标头,并且您无法设置任何其他标头。

No, you are wrong, but the direction fits ;)

The Output-Buffering buffers the output of a script. Thats (in short) everthing after echo or print. The thing with the headers is, that they only can get sent, if they are not already sent. But HTTP says, that headers are the very first of the transmission. So if you output something for the first time (in a request) the headers are sent and you can not set any other headers.

等风来 2024-10-13 13:18:32

输出缓冲 ob_start() 是一个告诉 PHP 在将输出数据发送到客户端之前将其作为字符串保存在变量中的过程。一般来说,PHP 将数据分段发送到浏览器。但是,如果我们使用输出缓冲功能,那么当 PHP 脚本结束时,它会将输出数据一次性发送到浏览器,而不是分批发送数据。

下面的代码可以帮助你清楚地理解它。

<?php
ob_start(); // output buffering is turned on
echo "Inside of output buffering section.";
$output = ob_get_clean(); // stopped the output store the output in the output variable

echo "Outside of output buffering section.<br>";
echo $output;
?>

/*
The output will be like this :

Inside of output buffering section.
Outside of output buffering section.

*/

ob_get_clean() 默默地丢弃缓冲区内容。

此外,还有另一个函数 ob_get_contents() 可以获取自我们调用 ob_start 以来收集的所有数据。

输出缓冲的优点

  1. 启用输出缓冲可减少下载时间并在浏览器中呈现 HTML。同时,它减少了 PHP 脚本的执行时间。
  2. 另一方面,当我们设置 cookie 时,有时我们会收到此警告“警告:无法修改标头信息 - 标头已由(输出)发送”,我们可以使用此输出缓冲来解决该问题。

您可以在此处查看更多相关信息。

Output Buffering ob_start(), is a process that tells PHP to hold the output data in a variable as a string before sending it to the client. In general, PHP sends the data to the browser in pieces. But if we use the output buffering feature, it sends the output data altogether to the browser in one piece when the PHP script ends instead of sending data in various pieces.

The following code helps you to understand it clearly.

<?php
ob_start(); // output buffering is turned on
echo "Inside of output buffering section.";
$output = ob_get_clean(); // stopped the output store the output in the output variable

echo "Outside of output buffering section.<br>";
echo $output;
?>

/*
The output will be like this :

Inside of output buffering section.
Outside of output buffering section.

*/

ob_get_clean() silently discards the buffer contents.

Also, there is another function ob_get_contents() that grabs all of the data gathered since we called ob_start.

Advantages of output buffering

  1. Enabling output buffering decreases the download time it takes and renders the HTML in the browser. At the same time, it decreases the PHP script execution time.
  2. On the other hand sometimes we get this warning "Warning: Cannot modify header information - headers already sent by (output)" when we set cookies, we can solve that issue using this output buffering.

You can see more about it that is explained here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文