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 poiflush().
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 clientOutput:
This will be bufferedob_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 5Su 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.
| Funzione | Invia il contenuto al livello successivo? | Mantiene il buffer aperto? |
|---|---|---|
ob_flush() | Sì | Sì — il buffering continua |
ob_end_flush() | Sì | No — chiude il buffer |
ob_get_clean() | No — lo restituisce come stringa | No — 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_compressionblocca 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 corrispondenteob_start()genera un warning. Verifica il livello attivo conob_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 chiamareob_flush()dopo ogniecho.
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.