为什么在PHP中使用输出缓冲? [英] Why use output buffering in PHP?

查看:94
本文介绍了为什么在PHP中使用输出缓冲?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在互联网上阅读了不少材料,不同的作者建议使用输出缓冲。有趣的是,大多数作者只是因为它允许将响应标题与实际内容进行混合而提出争议。坦白说,我认为负责任的Web应用程序不应该混合输出标题和内容,而Web开发人员应该在脚本中查找可能的逻辑缺陷,导致在产生输出后发送头文件。这是我反对 ob _ * 输出缓冲API的第一个参数。即使这样很方便,您也可以使用输出混合标题 - 这不足以使用它,除非需要快速修复脚本,这通常不是严重Web应用程序的目标和方式。另外,我认为大多数处理输出缓冲API的人都不会想到即使没有启用显式输出缓冲,PHP也可以与Web服务器结合使用它被插入,仍然执行一些内部缓冲。很容易检查 - 做一些短串的回声,睡10分钟,再做另一回音。使用浏览器请求您的脚本,并观看空白页面暂停10秒钟,之后显示两行。在有人说这是一个渲染文物,而不是流量之前,跟踪客户端和服务器之间的实际流量显示服务器已经生成了 Content-Length 值为整个输出 - 表示输出没有逐个发送,每个 echo 调用,但累积在一些缓冲区,然后在脚本终止发送。这是我显而易见的输出缓冲之一 - 为什么我们需要两个不同的输出缓冲区实现呢?可能是因为内部(不可访问的)PHP / Web服务器输出缓冲受到PHP开发人员无法控制的条件的限制,因此无法真正使用?



在任何case,我为一个,开始认为应该避免显式输出缓冲(系列 ob _ * 函数),并依赖于隐式的,协助它的良好的 flush 函数,必要时。也许如果网络服务器有一些保证,实际上是通过每次回显/打印调用向客户端发送输出,那么设置显式缓冲是有用的 - 在所有人不希望向客户端发送响应100字节块。但是有两个缓冲区的替代方案似乎有点无用的抽象层。



所以,最终,严重的Web应用程序是否需要输出缓冲?

解决方案



严重的Web应用程序在一个特定情况下需要输出缓冲:


您的应用程序想要控制某些第三方
代码的输出,但是没有API可以控制什么该代码发出。



在这种情况下,您可以在处理
控制之前调用 ob_start()对于那个代码,混乱了所写的(理想情况下是
的回调,或者通过检查缓冲区的内容,如果你必须)和
然后调用 ob_flush()


最终,PHP的ob_ 函数用于捕获某些其他位代码的缓冲区的机制可以ess与



如果您不需要检查或修改写入缓冲区的内容,则使用 ob_start()



很可能,你的认真的应用程序实际上是某种框架。






您已经有输出缓冲,无论如何



您不需要 ob_start()以便使用输出缓冲。您的网络服务器已经 缓冲输出。



使用 ob_start()不会让你更好地输出缓冲 - 它可以在事实上,通过囤积数据可以增加应用程序的内存使用量和延迟时间,网络服务器将已经发送给客户端。






可能 ob_start() ...



...为了方便刷新



在某些情况下,当您的应用程序最了解的某些条件,Web服务器刷新其缓冲区时,您可能希望控制。大多数情况下,您知道您刚刚完成了编写客户端可以使用的逻辑单位,并且您正在告诉Web服务器刷新现在而不是等待输出缓冲区填满。为了做到这一点,只需要正常地输出你的输出,并用 flush()标出。



ob_start 后来由 ob_end_flush()确定可能是最简单和适当的事情。



...如果您对某些标题负责



如果您的应用程序负责计算头,只能是在完全响应可用之后确定,则可以可以接受。但是,即使在这里,如果您不能比通过检查完整的输出缓冲区来导出标题更好,那么您也可以让Web服务器执行此操作(如果会的话)。网络服务器的代码,被编写,测试和编译 - 你不太可能改进它。



例如,只有设置 Content-Length 标题,如果您的应用程序在计算响应正文之前知道响应正文的长度。






没有恶作剧的恶作剧



你不应该 ob_start()




  • 打开使用,然后快速关闭资源,如内存,线程和数据库连接

  • 首先发送头文件,第二个

  • 执行所有的计算和错误处理在开始回应之前,可以,



如果你这样做,他们会造成技术性的债务,这样会让你有一天哭泣。 >

I have read quite a bit of material on Internet where different authors suggest using output buffering. The funny thing is that most authors argument for its use only because it allows for mixing response headers with actual content. Frankly, I think that responsible web applications should not mix outputting headers and content, and web developers should look for possible logical flaws in their scripts which result in headers being sent after output has been generated. This is my first argument against the ob_* output buffering API. Even for that little convenience you get - mixing headers with output - it is not a good enough reason to use it, unless one needs to hack up scripts fast, which is usually not the goal nor the way in a serious web application.

Also, I think most people dealing with the output buffering API do not think about the fact that even without the explicit output buffering enabled, PHP in combination with the web-server it is plugged into, still does some internal buffering anyway. It is easy to check - do an echo of some short string, sleep for say 10 seconds, and do another echo. Request your script with a browser and watch the blank page pause for 10 seconds, with both lines appearing thereafter. Before some say that it is a rendering artefact, not traffic, tracing the actual traffic between the client and the server shows that the server has generated the Content-Length header with an appropriate value for the entire output - suggesting that the output was not sent progressively with each echo call, but accumulated in some buffer and then sent on script termination. This is one of my gripes with explicit output buffering - why do we need two different output buffer implementations on top of one another? May it be because the internal (inaccessible) PHP/Web-server output buffering is subject to conditions a PHP developer cannot control, and is thus not really usable?

In any case, I for one, start to think one should avoid explicit output buffering (the series of ob_* functions) and rely on the implicit one, assisting it with the good flush function, when necessary. Maybe if there was some guarantee from the web server to actually send output to the client with each echo/print call, then it would be useful to set up explicit buffering - after all one does not want to send response to the client with some 100 byte chunks. But the alternative with two buffers seems like a somewhat useless layer of abstraction.

So, ultimately, do serious web applications need output buffering?

解决方案

Yes

Serious web applications need output buffering in one specific situation:

Your application wants control over what is output by some 3rd-party code, but there is no API to control what that code emits.

In that scenario, you can call ob_start() just before handing control to that code, mess around with what is written (ideally with the callback, or by examining the buffer contents if you must), and then calling ob_flush().

Ultimately, PHPs' ob_functions are a mechanism for capturing what some other bit of code does into a buffer you can mess with.

If you don't need to inspect or modify what is written to the buffer, there is nothing gained by using ob_start().

Quite likely, your 'serious application' is in fact a framework of some kind.


You already have output buffering, anyway

You don't need ob_start() in order to make use of output buffering. Your web-server already does buffer your output.

Using ob_start() does not get you better output buffering - it could in fact increase your application's memory usage and latency by 'hoarding' data which the web-server would otherwise have sent to the client already.


Maybe ob_start() ...

... for convenience when flushing

In some cases, you may want control over when the web-server flushes its buffer, based on some criteria which your application knows best. Most of the time, you know that you just finished writing a logical 'unit' which the client can make use of, and you're telling the web-server to flush now and not wait for the output buffer to fill up. To do this, it is simply necessary to emit your output as normal, and punctuate it with flush().

More rarely, you will want to withhold data from the web-server until you have enough data to send. No point interrupting the client with half of the news, especially if the rest of the news will take some time to become available. A simple ob_start later concluded by an ob_end_flush() may indeed be the simplest and appropriate thing to do.

... if you have responsibility for certain headers

If your application is taking responsibility for calculating headers which can only be determined after the full response is available, then it may be acceptable.

However, even here, if you can't do any better than deriving the header by inspecting the complete output buffer, you might as well let the web-server do it (if it will). The web-server's code, is written, tested, and compiled - you are unlikely to improve on it.

For example, it would only be useful to set the Content-Length header if your application knows the length of the response body after before it computes the response body.


No panacea for bad practices

You should not ob_start() to avoid the disciplines of:

  • opening, using and quickly closing resources such as memory, threads and database connections
  • emitting headers first, and the body second
  • doing all the calculations and error handling you can, before beginning the response

If you do these, they will cause technical debt which will make you cry one day.

这篇关于为什么在PHP中使用输出缓冲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆