W3docs

Funzione PHP ob_gzhandler(): Tutto quello che devi sapere

Scopri come usare ob_gzhandler() in PHP per comprimere l'output con gzip, ridurre la larghezza di banda e velocizzare il caricamento delle pagine.

Comprimere HTML, CSS o JSON prima che lasci il server riduce la larghezza di banda e velocizza il caricamento delle pagine. La funzione integrata ob_gzhandler() di PHP è un modo pronto all'uso per farlo direttamente nello script: la si passa al buffer di output, e comprimerebbe con gzip tutto ciò che lo script restituisce tramite echo — ma solo quando il browser dichiara di poterlo decomprimere. Questo articolo tratta la sua sintassi, un esempio completo, come negozia con il client, le insidie più comuni e quando conviene usarla rispetto a lasciare che sia il server a gestire la compressione.

Cosa fa la funzione ob_gzhandler()

ob_gzhandler() è una callback progettata per essere passata a ob_start(). Non la si chiama mai direttamente — è il sistema di output buffering a chiamarla con il contenuto bufferizzato come argomento, e restituisce i byte compressi (oppure, quando la compressione non è possibile, i byte invariati).

Prima di comprimere, ispeziona l'intestazione Accept-Encoding della richiesta e sceglie il miglior schema supportato:

  • Se il client supporta gzip, comprime con gzip e imposta Content-Encoding: gzip.
  • Se il client supporta solo deflate, usa deflate al suo posto.
  • Se il client non supporta nessuno dei due, restituisce il contenuto invariato e ob_start() fallisce (restituisce false), quindi la risposta viene inviata non compressa.

Poiché imposta automaticamente le intestazioni di risposta Content-Encoding e Vary, è necessario registrarla prima che venga inviato qualsiasi output — consulta headers_sent() se si riceve un errore "headers already sent".

Sintassi

ob_start("ob_gzhandler");

ob_gzhandler() accetta internamente due parametri ($buffer e $mode), ma non li si fornisce mai — lo fa il motore di buffering. Si registra semplicemente la stringa "ob_gzhandler" come nome della callback.

Un esempio completo

<?php

ob_start("ob_gzhandler");
echo "This will be compressed using gzip compression";
ob_end_flush();
?>

Qui, ob_start() apre un buffer di output con ob_gzhandler() come handler, l'echo scrive in quel buffer invece di inviare direttamente al client, e ob_end_flush() chiude il buffer e invia il suo contenuto (ora compresso). Dal punto di vista del visitatore non cambia nulla — il browser decomprime la risposta in modo trasparente — ma viaggiano meno byte sulla rete.

Fallback per i client che non supportano gzip

ob_start("ob_gzhandler") restituisce false quando il client non dichiara supporto per gzip o deflate. Se lo si ignora, non viene avviato alcun buffer e il successivo ob_end_flush() genererà un avviso. Bisogna controllare il valore restituito e ricorrere a un buffer semplice:

<?php
if (!ob_start("ob_gzhandler")) {
    ob_start(); // plain buffer, no compression
}
echo "Served either compressed or uncompressed, but always buffered.";
ob_end_flush();
?>

Impostare il livello di compressione

ob_start() non accetta un livello di compressione — ob_gzhandler() usa quello predefinito di zlib (controllato dall'impostazione INI zlib.output_compression_level, default -1). Per forzare un livello specifico da 1 (più veloce, meno compressione) a 9 (più lento, dimensione minore), si bypassa ob_gzhandler() e si usa una propria callback con gzencode():

<?php
ob_start(function ($buffer) {
    return gzencode($buffer, 9);
});
echo "Compressed at the maximum level.";
ob_end_flush();
?>

Attenzione: questa callback personalizzata non negozia Accept-Encoding né imposta Content-Encoding: gzip automaticamente — ob_gzhandler() fa entrambe le cose in automatico. Se si crea una propria callback, bisogna inviare manualmente quelle intestazioni, il che spiega perché ob_gzhandler() rimanga comoda per il caso comune.

ob_gzhandler() vs. zlib.output_compression

PHP offre un secondo modo, ancora più semplice, per comprimere l'output: la direttiva INI zlib.output_compression. Impostata su On (o una soglia in byte), PHP comprime con gzip l'intera risposta senza alcun codice aggiuntivo:

zlib.output_compression = On

I due approcci sono mutualmente esclusivi — abilitare zlib.output_compression mentre si chiama anche ob_start("ob_gzhandler") genera un avviso e non produce alcuna doppia compressione utile. Si preferisce zlib.output_compression quando si può modificare php.ini o usare ini_set(), riservando ob_gzhandler() ai casi in cui serve all'interno di uno script su cui non si controlla la configurazione.

Insidie comuni

  • Non sovrapporre livelli gzip. Combinare ob_gzhandler() con la compressione a livello server (Nginx/Apache gzip) o con zlib.output_compression può produrre risposte corrotte, con doppia codifica.
  • Registrarlo per primo. Qualsiasi echo precedente, spazio bianco prima di <?php, o BOM nel file invia le intestazioni in anticipo e compromette la compressione.
  • Non adatto a dati già compressi. Comprimere con gzip JPEG, PNG o ZIP spreca CPU per un guadagno di dimensioni quasi nullo.
  • Richiede l'estensione zlib. ob_gzhandler() richiede che PHP sia compilato con zlib (quasi sempre lo è, ma vale la pena saperlo su build minimali).

Conclusione

La funzione ob_gzhandler() offre un modo semplice e autonomo per comprimere con gzip l'output di PHP: la si registra come callback di ob_start() e si occupa da sola di negoziare la codifica e impostare le intestazioni. Nelle configurazioni moderne, tuttavia, di solito si preferisce la compressione a livello server (Nginx, Apache) o un CDN che gestisca gzip/brotli — questo scarica la CPU da PHP e comprime anche le risorse statiche. Conoscere ob_gzhandler() resta comunque importante per codebase legacy e script in cui non è possibile toccare la configurazione del server. Per un quadro più ampio del lavoro con i buffer, consulta la panoramica su PHP Output Control.

Pratica

Pratica
Qual è lo scopo di ob_gzhandler in PHP?
Qual è lo scopo di ob_gzhandler in PHP?
Was this page helpful?