2010-12-09 16 views
205

¿Se usa ob_start() para output buffering de modo que los encabezados estén almacenados en un búfer y no se envíen al navegador? ¿Estoy teniendo sentido aquí? Si no, ¿por qué deberíamos usar ob_start()?¿De qué sirve ob_start() en php?

Respuesta

326

Piense en ob_start() diciendo "Comience recordando todo lo que normalmente se generará, pero no haga absolutamente nada con eso todavía".

Por ejemplo:

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

Hay otras dos funciones que normalmente se empareje con: ob_get_contents(), que, básicamente, que lo que ha sido "salvado" a la memoria intermedia desde que se enciende con ob_start() da, y luego ob_end_clean() o ob_flush(), que o bien deja de guardar cosas y descarta lo que se guardó, o deja de guardar y lo emite todo a la vez, respectivamente.

+33

Gran explicación. Daría un paso más y reemplazaría 'ob_get_contents()' con 'ob_get_clean()' y eliminaría 'ob_end_clean()' ya que 'ob_get_clean()' esencialmente realiza ambas funciones. Referencia: http://php.net/manual/en/function.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5) –

+0

Supongo que el almacenamiento en búfer de salida debe estar habilitado en el orden del archivo .ini para llamar a 'ob_start();' ¿Es correcto? ¿Qué pasa si no está habilitado? –

+4

@Riley Dutton Usted no está diciendo que por qué se usa ob_start() –

3

Esta función no es solo para encabezados. Puedes hacer muchas cosas interesantes con esto. Ejemplo: Se puede dividir la página en secciones y utilizar de esta manera:

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

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

Puede capturar la salida que se genera aquí y agregarlo en dos lugares totalmente diferentes en su diseño.

+0

Este tipo de parece lo que estoy buscando. Necesito renderizar cosas en 'secciones' (piense en archivos JS y CSS), pero necesito poder llamarlas dentro de la plantilla (que se carga más adelante que el encabezado) ... Así que si llamo "$ this" -> addcss ('specificCSStoThisView'); " Quiero que se muestre entre las etiquetas . Parece que no puedo googlear esto, sin embargo. ¿Podrías quizás señalarme en la dirección correcta? ¡Gracias! – NoobishPro

28

Lo tiene al revés. ob_start no almacena en búfer los encabezados, sino que almacena el contenido. El uso de ob_start le permite mantener el contenido en un búfer del lado del servidor hasta que esté listo para mostrarlo.

Esto se usa comúnmente para que las páginas puedan enviar encabezados "después" de que ya hayan "enviado" algún contenido (es decir, que decida redirigir a la mitad de la representación de una página).

+3

+1 Yo también estaba confundido en cuanto al uso real de la función. Su respuesta con respecto a su uso durante la "redirección" me recordó todas las veces que tuve el error "Encabezados ya enviados".Gracias – pat

0

No, estás equivocado, pero la dirección se ajusta;)

La salida amortiguadoras del amortigua la salida de un guión. Eso es (en resumen) todo después de echo o print. Lo que pasa con los encabezados es que solo pueden enviarse, si aún no han sido enviados. Pero HTTP dice que los encabezados son los primeros de la transmisión. Por lo tanto, si muestra algo por primera vez (en una solicitud), los encabezados se envían y no puede establecer otros encabezados.

109

Utilizo esto para poder salir de PHP con mucho HTML pero no renderizarlo. Me ahorra almacenarlo como una cadena que deshabilita la codificación de colores.

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

En lugar de:

<?php 
$content = '<div> 
    <span>text</span> 
    <a href="#">link</a> 
</div>'; 
?> 
+1

¿Se puede utilizar esto como una forma de tener múltiples páginas html dentro de un PHP y llamarlas a través de GET? – joshkrz

+0

Supongo que sí, pero no parece una buena idea. Sería mejor cargarlos desde plantillas separadas. –

+0

Tenga en cuenta que esta técnica utiliza ['ob_get_clean()'] (http://php.net/manual/en/function.ob-end-clean.php), no ['ob_end_clean()'] (http: // php.net/manual/en/function.ob-end-clean.php) – Blazemonger

7

esto es para aclarar aún más la respuesta JD Isaaks ...

El problema se encuentra con frecuencia es que se está utilizando php a html salida de muchos diferentes fuentes de php, y esas fuentes a menudo, por cualquier razón, la salida a través de diferentes formas.

A veces tiene contenido html literal que desea enviar directamente al navegador; otras veces la salida se crea dinámicamente (en el lado del servidor).

El contenido dinámico es siempre (?) Va a ser una cadena. Ahora debe combinar este html dinámico codificado con cualquier html literal, directo a visualización ... en una estructura de nodo html significativa.

Esto generalmente obliga al desarrollador a envolver todo ese contenido directo en una cadena (como JD Isaak estaba discutiendo) para que pueda ser entregado/insertado adecuadamente junto con el html dinámico ... aunque usted realmente no lo quiero envuelto.

Pero al usar los métodos ob _ ## puede evitar ese desorden en la envoltura de cuerdas. El contenido literal es, en cambio, salida al búfer. Luego, en un solo paso, todo el contenido del búfer (todo su html literal) se concatena en su cadena dynamic-html.

(Mi ejemplo muestra que html literal es enviado al búfer, que luego se agrega a una cadena html ... mire también el ejemplo de JD Isaaks para ver 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> 
58

La respuesta aceptada aquí se describe lo que hace ob_start() - no por qué se usa (que era la pregunta hecha).

Como se indica en otra parte ob_start() crea un búfer en el que se escribe la salida.

Pero nadie ha mencionado que es posible acumular múltiples búferes dentro de PHP. Ver ob_get_level().

En cuanto al por qué ....

  1. Envío de HTML al navegador en trozos más grandes da una ventaja de rendimiento de una sobrecarga de la red reducida.

  2. pasar los datos de PHP en trozos más grandes da una ventaja en el rendimiento y la capacidad de reducir el número de cambios de contexto requerida

  3. pasar trozos grandes de datos a mod_gzip/mod_deflate da una ventaja de rendimiento porque la compresión puede ser mas eficiente

  4. amortiguar la salida significa que todavía puede manipular las cabeceras HTTP adelante en el código

  5. explícitamente lavado la memoria intermedia después de la salida de la [cabeza] .... [/ cabeza] puede permitir que el navegador para comenzar a reunir otros recursos para la página antes de que se complete la secuencia HTML.

  6. La captura de la salida en un búfer significa que puede redirigir a otras funciones como el correo electrónico, o copiado en un archivo como una representación en caché del contenido

7

Prefiero:

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