A che serve ob_start () in php?


298

Viene ob_start()utilizzato in output bufferingmodo che le intestazioni vengano memorizzate nel buffer e non inviate al browser? Sto dando un senso qui? In caso contrario, perché dovremmo usare ob_start()?

Risposte:


481

Pensa ob_start()a dire "Inizia a ricordare tutto ciò che normalmente verrebbe emesso, ma non farci ancora nulla".

Per esempio:

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

Ci sono altre due funzioni con cui in genere lo abbini:, ob_get_contents()che in pratica ti dà tutto ciò che è stato "salvato" nel buffer da quando è stato acceso ob_start(), e poi ob_end_clean()o ob_flush(), che smette di salvare le cose e scarta tutto ciò che è stato salvato, o interrompe il salvataggio ed emette tutto in una volta, rispettivamente.


55
Ottima spiegazione Vorrei fare un ulteriore passo avanti e sostituire ob_get_contents()con ob_get_clean()e rimuovere ob_end_clean()poiché ob_get_clean()essenzialmente svolge entrambe le funzioni. Riferimento: php.net/manual/en/function.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5)
Con Antonakos

Presumo che il buffering dell'output debba essere abilitato nell'ordine del file .ini per chiamare ob_start();È corretto? Cosa succede se non è abilitato?
Kevin Wheeler,

5
@Riley Dutton Non stai dicendo che perché viene usato ob_start ()
Vishnu R Nair

Ha avuto lo stesso problema, dopo aver corretto il mio codice con ob_end_cleanesso funziona come un fascino! Grazie @Riley Dutton
Martins

160

Lo uso in modo da poter uscire da PHP con molto HTML ma non renderlo. Mi evita di memorizzarlo come una stringa che disabilita il codice colore IDE.

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

Invece di:

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

1
Può essere usato come un modo per avere più pagine html all'interno di un PHP e chiamarle tramite GET?
joshkrz,

1
Suppongo di sì, ma non sembra una buona idea. Sarebbe meglio caricarli da modelli separati.
JD Isaacks,

1
Si noti che questa tecnica utilizza ob_get_clean(), non ob_end_clean()
Blazemonger,

11
Non ci ho mai pensato, è un modo incredibilmente intuitivo di sviluppo IDE! Inoltre, rimuove il mio bisogno di avere Javascript o HTML come stringa nel mio PHP, in costante fuga \ "ecc., Il che è fastidioso
J-Dizzle,

1
Il tuo visual fornisce un'immagine chiara dei vantaggi dell'utilizzo di ob_start.
Klewis

86

La risposta accettata qui descrive cosa ob_start()non fa - perché non è stata usata (quale era la domanda posta).

Come indicato altrove, ob_start()crea un buffer in cui viene scritto l'output.

Ma nessuno ha menzionato che è possibile impilare più buffer all'interno di PHP. Vedi ob_get_level ().

Per quanto riguarda il perché ....

  1. L'invio di HTML al browser in blocchi più grandi offre un vantaggio in termini di prestazioni grazie a un overhead di rete ridotto.

  2. Passare i dati al di fuori di PHP in blocchi più grandi offre un vantaggio in termini di prestazioni e capacità riducendo il numero di switch di contesto richiesti

  3. Passare grandi quantità di dati a mod_gzip / mod_deflate offre un vantaggio in termini di prestazioni in quanto la compressione può essere più efficiente.

  4. buffering dell'output significa che è ancora possibile manipolare le intestazioni HTTP più avanti nel codice

  5. svuotare esplicitamente il buffer dopo aver emesso il [head] .... [/ head] può consentire al browser di iniziare il marshalling di altre risorse per la pagina prima che il flusso HTML venga completato.

  6. Catturare l'output in un buffer significa che può essere reindirizzato ad altre funzioni come la posta elettronica o copiato in un file come rappresentazione memorizzata nella cache del contenuto


29

Lo hai al contrario. ob_start non bufferizza le intestazioni, ma buffer il contenuto. L'utilizzo ob_startconsente di conservare il contenuto in un buffer lato server fino a quando non si è pronti a visualizzarlo.

Questo è comunemente usato in modo che le pagine possano inviare le intestazioni "dopo" che hanno già "inviato del contenuto" (ovvero, decidere di reindirizzare a metà del rendering di una pagina).


3
+1 Anche io ero confuso riguardo all'effettivo utilizzo della funzione. La tua risposta relativa al suo utilizzo durante il "reindirizzamento" mi ha ricordato tutte le volte in cui ho avuto l'errore "Intestazioni già inviate". Grazie
pat

13

Preferisco:

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

8

questo per chiarire ulteriormente la risposta di JD Isaaks ...

Il problema che incontri spesso è che stai usando php per generare html da molte fonti php diverse, e queste fonti sono spesso, per qualsiasi motivo, in uscita in modi diversi.

A volte hai un contenuto html letterale che desideri inviare direttamente al browser; altre volte l'output viene creato in modo dinamico (lato server).

Il contenuto dinamico sarà sempre (?) Una stringa. Ora devi combinare questo html dinamico rigoroso con qualsiasi html letterale, direttamente da visualizzare ... in una struttura di nodi html significativa.

Questo di solito costringe lo sviluppatore a racchiudere tutto quel contenuto diretto per la visualizzazione in una stringa (come stava discutendo JD Isaak) in modo che possa essere correttamente consegnato / inserito insieme al HTML dinamico ... anche se in realtà non lo fai lo voglio avvolto.

Ma usando i metodi ob _ ## puoi evitare quel casino di stringhe. Il contenuto letterale viene invece emesso nel buffer. Quindi, con un semplice passaggio, l'intero contenuto del buffer (tutto il tuo html letterale) viene concatenato nella tua stringa html dinamica.

(Il mio esempio mostra che l'html letterale viene emesso nel buffer, che viene quindi aggiunto a una stringa html ... guarda anche l'esempio di JD Isaaks per vedere il wrapping delle stringhe di 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>

4

Questa funzione non è solo per le intestazioni. Puoi fare molte cose interessanti con questo. Esempio: puoi dividere la tua pagina in sezioni e usarla in questo modo:

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

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

È possibile acquisire l'output generato qui e aggiungerlo in due punti totalmente diversi nel layout.


Questo tipo di sembra quello che sto cercando. Devo renderizzare le cose in 'sezioni' (pensa ai file JS e CSS), ma devo essere in grado di chiamarle all'interno del modello (che viene caricato dopo l'intestazione) ... Quindi se chiamo "$ this- > addcss ( 'specificCSStoThisView');" Voglio renderlo tra i tag <head>. Tuttavia, non riesco a cercarlo su Google. Potresti forse indicarmi la giusta direzione? Grazie!
NoobishPro,

2

Le seguenti cose non sono menzionate nelle risposte esistenti: Configurazione dimensione buffer Intestazione HTTP e Nesting.

Configurazione della dimensione del buffer per 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.

Il codice sopra migliora le prestazioni del server poiché PHP invierà grosse quantità di dati, ad esempio 4KB (senza chiamata ob_start, php invierà ogni eco al browser).

Se inizi a eseguire il buffering senza le dimensioni del blocco (ad es. Un semplice ob_start ()), la pagina verrà inviata una volta alla fine dello script.

Il buffering dell'output non influisce sulle intestazioni HTTP, ma vengono elaborate in modo diverso. Tuttavia, a causa del buffering è possibile inviare le intestazioni anche dopo l'invio dell'output, poiché è ancora nel 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

Ben spiegato qui: https://phpfashion.com/everything-about-output-buffering-in-php


0

No, ti sbagli, ma la direzione si adatta;)

Output-Buffering bufferizza l'output di uno script. Questo è (in breve) tutto dopo echoo print. La cosa con le intestazioni è che possono essere inviati solo se non sono già stati inviati. Ma HTTP afferma che le intestazioni sono le prime della trasmissione. Quindi, se si emette qualcosa per la prima volta (in una richiesta), le intestazioni vengono inviate e non è possibile impostare altre intestazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.