Búfer PHP ob_flush () frente a flush ()

79

Cuál es la diferencia entre ob_flush() yflush() y por qué debo llamar a ambos?

La ob_flush()referencia dice:

Esta función enviará el contenido del búfer de salida (si lo hubiera).

La flush()referencia dice:

Vacía los búferes de escritura de PHP y cualquier backend que PHP esté usando (CGI, un servidor web, etc.).

Sin embargo, continúa diciendo:

[it] puede que no pueda anular el esquema de almacenamiento en búfer de su servidor web ...

Entonces, me parece que podría usar ob_flush()todo el tiempo. Sin embargo, obtengo resultados extraños cuando hago eso. ¿Alguien podría explicar en términos simples qué está pasando aquí?

Ben
fuente

Respuestas:

75

ob_flushenvía un búfer iniciado por la aplicación. Puede haber varios anidados ob_start()en cualquier script PHP.ob_flushpasa el contenido actual a la capa superior.

PHP mismo podría (a su propia discreción) almacenar en búfer la salida. Esto depende del back-end. Pero generalmente FastCGItiene un búfer de socket por sí solo. Por lo tantoflush() , también debe invocarse para enviar el contenido actual al servidor web.

Y ahora el servidor web podría implementar por sí mismo otro esquema de almacenamiento en búfer ( mod_deflateo filtro de contenido), sobre el que usted no tiene ninguna influencia. Pero esto es raro, ya que debe configurarse específicamente.

De todos modos, usa ambos.

mario
fuente
11
Utilice ob_flush y flush y utilícelos en ese orden.
Robino
17
El detalle importante que falta en esta respuesta es la output_bufferingopción de configuración, cuyo valor predeterminado en las versiones de producción de php.ini es 4096. Eso significa que cuando se inicia cualquier script PHP, los primeros 4096 bytes de salida se almacenan en búfer (en un búfer que se puede descargar con ob_flush()). Por eso es necesario utilizar ob_flush()tan bien como flush(). Deshabilitar a output_bufferingtravés de php.ini o llamar ob_end_clean()o ob_end_flush()al comienzo del script elimina esta necesidad.
Mark Amery
Gracias @MarkAmery, pero ob_end_clean()al "inicio del guión" parece contradictorio. ¿Quiere decir que deberíamos incluir esto poco después ob_start()y antes de los dos lavados?
Khom Nazid
Bueno, tengo un ob_start()y un ob_end_clean()al comienzo del guión. Luego, después de cualquier "eco" durante la secuencia de comandos, también incluyo ob_flush(); flush();, y espero que mientras la secuencia de comandos esté tardando, todo lo que se ha hecho hasta ahora se mostrará en la pantalla (en el navegador). Pero no se publica nada hasta el final. ¿Qué me estoy perdiendo?
Khom Nazid
1
@KhomNazid Una observación del navegador no es lo mismo que depurar el flujo HTTP. Es poco probable que la salida incremental y retrasada a un DOM HTML incompleto sea visible. Realice algunas pruebas de CLI con su configuración actual. (Y luego, y solo entonces, comience una pregunta diferente al respecto.)
mario
33

ob_flushvacía los búferes de salida que creó con una función comoob_start

flush descarga la salida almacenada en búfer del propio script PHP a su llamador

Dan Grossman
fuente
25

ob_flush()es una descarga de alto nivel. Vacía los búferes de alto nivel y coloca todo el contenido en los búferes internos de bajo nivel listos para enviar.

  • Tenga en cuenta que la ob_familia de funciones crea pilas de búferes, por lo que escribir a ciegas en ob_flush()todas partes le dará "resultados extraños" si el código se escribió para aprovechar esta acumulación.

flush() es un vaciado de bajo nivel, que indica a PHP que vaciar sus búferes de datos internos de bajo nivel.

Aún debajo de eso, habrá búferes de capa de socket; debajo de eso, hay búferes de capa de red. Y, en el nivel más bajo, la cola de electrones bajando por el cable de datos.

Carreras de ligereza en órbita
fuente
Bueno, tengo un ob_start()y un ob_end_clean()al comienzo del guión. Luego, después de cualquier "eco" durante la secuencia de comandos, también incluyo ob_flush(); flush();, y espero que mientras la secuencia de comandos esté tardando, todo lo que se ha hecho hasta ahora se mostrará en la pantalla (en el navegador). Pero no se publica nada hasta el final. ¿Qué me estoy perdiendo?
Khom Nazid
@KhomNazid Almacenamiento en búfer por etapas intermedias, como el servidor web, los proxies, su navegador ...
Lightness Races in Orbit
11

Supongo que esto está en relación con su pregunta anterior . La ventaja significativa de usar el almacenamiento en búfer de salida es cuando se usa junto con la compresión de datos. Si no está consumiendo ob_gzhandler, hay poco que ganar. flushsolo confirmará los datos de salida que aún estén en el servidor. Con ob_starty sus contrapartes ob_flush, ob_end_cleany ob_end_flushlo que esté esperando ser comprimido (mire flushy ob_flushcomo referencia a diferentes cubos, obenvía datos flush, flushenvía datos al navegador, puede no ser exacto, pero esa es la idea) se empaquetará y enviará al cliente. .

bcosca
fuente
Gracias, la analogía del cubo es un buen ejemplo.
Ben