W3docs

Funzione PHP ob_flush(): tutto quello che devi sapere

Scopri come usare ob_flush() in PHP per inviare al client il contenuto del buffer di output in modo incrementale, senza terminare il buffering.

Per impostazione predefinita PHP trattiene l'output in un buffer e lo invia al client tutto in una volta. A volte vuoi invece trasmettere ciò che hai prodotto fino a quel momento al browser senza terminare il buffer — ad esempio per inviare in streaming i risultati di un lungo report riga per riga, o per mostrare l'avanzamento durante un'operazione lenta. La funzione ob_flush() fa esattamente questo: invia il contenuto del buffer di output attivo al livello successivo e poi lo svuota, mantenendo il buffering attivo così puoi continuare a raccogliere output. Questo capitolo spiega come ob_flush() si inserisce nella catena di output buffering di PHP, quando usarla e le insidie in cui è facile cadere.

Cosa fa ob_flush()

ob_flush() invia il contenuto del buffer di output più in alto nello stack al livello successivo — il buffer successivo nello stack, oppure il livello di scrittura interno di PHP se questo è l'unico buffer. Dopo il flush, quel buffer viene svuotato ma rimane aperto, così i successivi echo vengono di nuovo catturati.

Signature:  ob_flush(): void
Returns:    nothing (void); emits a warning if no buffer is active
PHP:        4.0+ (return type became void in PHP 8.0)

Due concetti sono facili da confondere:

  • ob_flush() sposta i dati fuori dal buffer PHP ma non garantisce che raggiungano il browser. Potrebbe esserci un altro buffer sopra, più il buffer di scrittura interno di PHP e il buffer del server web.
  • flush() spinge i buffer di scrittura di PHP verso il client. Per far arrivare effettivamente i byte sulla rete si chiamano tipicamente entrambi, in ordine: ob_flush() e poi flush().

Deve essere abbinata a ob_start(). Chiamare ob_flush() quando nessun buffer è attivo genera un notice/warning e non fa nulla.

Sintassi

ob_flush();

Non accetta argomenti e non restituisce alcun valore.

Esempio di base

Abilitare il buffering, scrivere qualcosa, quindi eseguire il flush:

<?php

ob_start();              // 1. Enable output buffering
echo "This will be buffered";
ob_flush();              // 2. Flush PHP buffer to the next level
flush();                 // 3. Push it toward the client

Output:

This will be buffered

ob_start() apre un buffer, l'echo viene catturato al suo interno, ob_flush() rilascia quel testo e flush() lo spinge verso il browser. La cosa importante è che il buffer rimane aperto dopo questa operazione — si potrebbe fare echo e flush di nuovo.

Invio progressivo dell'output in streaming

L'uso reale più comune di ob_flush() è inviare l'output a blocchi in modo che l'utente veda i risultati man mano che vengono prodotti, invece di aspettare che l'intero script termini:

<?php

ob_start();

for ($i = 1; $i <= 5; $i++) {
    echo "Processing item $i\n";
    ob_flush();          // hand this line to the next level
    flush();             // and on toward the browser
    // sleep(1);         // (a real task would do work here)
}

Output:

Processing item 1
Processing item 2
Processing item 3
Processing item 4
Processing item 5

Su un server reale con sleep(1) decommentato, ogni riga apparirebbe a distanza di un secondo invece di comparire tutte alla fine.

ob_flush() vs. ob_end_flush() vs. ob_get_clean()

Scegliere la funzione di flush sbagliata è la fonte più comune di bug. Si differenziano in due modi: se il buffer rimane aperto e dove va il contenuto.

FunzioneInvia il contenuto al livello successivo?Mantiene il buffer aperto?
ob_flush() — il buffering continua
ob_end_flush()No — chiude il buffer
ob_get_clean()No — lo restituisce come stringaNo — chiude il buffer

Usa ob_flush() quando vuoi emettere avanzamento ma continuare il buffering. Usa ob_end_flush() quando hai completamente finito. Usa ob_get_clean() quando vuoi catturare il buffer in una variabile invece di inviarlo.

Insidie comuni

  • Il buffering lato server può comunque trattenere l'output. Apache, Nginx (buffering FastCGI), la compressione gzip e i proxy possono tenere i byte ricevuti finché non ne hanno "abbastanza". ob_flush() + flush() controllano solo la parte di PHP.
  • zlib.output_compression blocca lo streaming. Quando la compressione gzip dell'output è attiva, i flush intermedi vengono di solito bufferizzati per la compressione, quindi i blocchi non arriveranno a spizzichi. Disabilitala per gli endpoint di streaming.
  • Nessun buffer = warning. Chiamare ob_flush() senza un corrispondente ob_start() genera un warning. Verifica il livello attivo con ob_get_level() se non sei sicuro.
  • Svuota il buffer. Dopo ob_flush() il buffer viene azzerato, quindi non è possibile leggerne il contenuto precedente in seguito.
  • Forzare il flush immediato globalmente. ob_implicit_flush(true) fa sì che ogni istruzione di output esegua automaticamente il flush, eliminando la necessità di chiamare ob_flush() dopo ogni echo.

Conclusione

ob_flush() invia il buffer di output corrente al livello successivo mantenendo il buffering abilitato, rendendola lo strumento giusto per trasmettere in streaming avanzamento o risposte di grandi dimensioni in modo incrementale. Ricorda la catena: ob_start() apre il buffer, ob_flush() rilascia il suo contenuto al livello successivo e flush() lo spinge verso il client — e che il buffering lato server o la compressione gzip possono comunque ritardare la consegna indipendentemente da ciò che fa il codice PHP.

Pratica

Pratica
Cosa fa la funzione ob_flush() in PHP?
Cosa fa la funzione ob_flush() in PHP?
Was this page helpful?