Fonction PHP ob_gzhandler() : Tout ce que vous devez savoir
Découvrez comment utiliser ob_gzhandler() en PHP pour compresser votre sortie, réduire la bande passante et accélérer le chargement de vos pages.
Compresser du HTML, du CSS ou du JSON avant qu'il ne quitte le serveur réduit la bande passante et accélère le chargement des pages. La fonction intégrée ob_gzhandler() de PHP est une solution prête à l'emploi pour y parvenir depuis votre script : vous la transmettez au tampon de sortie, et elle compresse en gzip tout ce que votre script affiche — mais uniquement lorsque le navigateur indique qu'il peut décompresser. Cet article couvre sa syntaxe, un exemple complet, la façon dont elle négocie avec le client, les pièges courants et le moment où vous devriez l'utiliser plutôt que de laisser le serveur gérer la compression.
Ce que fait la fonction ob_gzhandler()
ob_gzhandler() est un callback conçu pour être transmis à ob_start(). Vous ne l'appelez jamais directement — c'est le système de tampon de sortie qui l'appelle avec le contenu mis en tampon comme argument, et elle renvoie les octets compressés (ou, si la compression est impossible, non modifiés).
Avant de compresser, elle inspecte l'en-tête Accept-Encoding de la requête et choisit le meilleur schéma pris en charge :
- Si le client prend en charge gzip, elle compresse avec gzip et définit
Content-Encoding: gzip. - Si le client ne prend en charge que deflate, elle utilise deflate à la place.
- Si le client ne prend en charge aucun des deux, elle renvoie le contenu intact et
ob_start()échoue (retournefalse), donc la réponse est envoyée non compressée.
Comme elle définit automatiquement les en-têtes de réponse Content-Encoding et Vary, vous devez l'enregistrer avant tout envoi de sortie — consultez headers_sent() si vous rencontrez une erreur « headers already sent ».
Syntaxe
ob_start("ob_gzhandler");ob_gzhandler() prend deux paramètres en interne ($buffer et $mode), mais vous ne les fournissez jamais — c'est le moteur de mise en tampon qui le fait. Vous n'avez qu'à enregistrer la chaîne "ob_gzhandler" comme nom de callback.
Un exemple complet
<?php
ob_start("ob_gzhandler");
echo "This will be compressed using gzip compression";
ob_end_flush();
?>Ici, ob_start() ouvre un tampon de sortie avec ob_gzhandler() comme gestionnaire, le echo écrit dans ce tampon plutôt que directement chez le client, et ob_end_flush() ferme le tampon et envoie son contenu (désormais compressé). Du point de vue du visiteur, rien ne change — le navigateur décompresse la réponse de façon transparente — mais moins d'octets transitent sur le réseau.
Repli pour les clients qui ne prennent pas en charge gzip
ob_start("ob_gzhandler") retourne false quand le client n'annonce pas la prise en charge de gzip ou deflate. Si vous ignorez cela, aucun tampon n'est démarré et votre ob_end_flush() ultérieur générera un avertissement. Vérifiez la valeur de retour et repliez-vous sur un tampon simple :
<?php
if (!ob_start("ob_gzhandler")) {
ob_start(); // plain buffer, no compression
}
echo "Served either compressed or uncompressed, but always buffered.";
ob_end_flush();
?>Définir le niveau de compression
ob_start() n'accepte pas de niveau de compression — ob_gzhandler() utilise la valeur par défaut de zlib (contrôlée par le paramètre INI zlib.output_compression_level, défaut -1). Pour forcer un niveau spécifique de 1 (le plus rapide, moins de compression) à 9 (le plus lent, taille la plus petite), ignorez ob_gzhandler() et utilisez votre propre callback avec gzencode() :
<?php
ob_start(function ($buffer) {
return gzencode($buffer, 9);
});
echo "Compressed at the maximum level.";
ob_end_flush();
?>Notez que ce callback personnalisé ne négocie pas Accept-Encoding ni ne définit Content-Encoding: gzip pour vous — ob_gzhandler() fait les deux automatiquement. Si vous créez le vôtre, vous devez envoyer ces en-têtes vous-même, ce qui explique pourquoi ob_gzhandler() reste pratique pour le cas courant.
ob_gzhandler() vs. zlib.output_compression
PHP offre une deuxième façon, encore plus simple, de compresser la sortie : la directive INI zlib.output_compression. Définissez-la à On (ou un seuil en octets) et PHP compresse en gzip la réponse entière sans aucun code :
zlib.output_compression = OnLes deux approches sont mutuellement exclusives — activer zlib.output_compression tout en appelant ob_start("ob_gzhandler") déclenche un avertissement et ne double-compresse rien d'utile. Préférez zlib.output_compression lorsque vous pouvez modifier php.ini ou utiliser ini_set(), et réservez ob_gzhandler() pour les cas où vous en avez besoin dans un script dont vous ne contrôlez pas la configuration.
Pièges courants
- N'imbriquement pas les couches gzip. Combiner
ob_gzhandler()avec la compression au niveau du serveur (Nginx/Apachegzip) ou aveczlib.output_compressionpeut produire des réponses corrompues et doublement encodées. - Enregistrez-le en premier. Tout
echopréalable, espace blanc avant<?php, ou BOM dans le fichier envoie les en-têtes prématurément et casse la compression. - Pas pour les données binaires déjà compressées. Compresser en gzip des JPEG, PNG ou ZIP gaspille du CPU pour un gain de taille quasi nul.
- L'extension zlib est requise.
ob_gzhandler()nécessite que PHP soit compilé avec zlib (c'est presque toujours le cas, mais utile à savoir sur les builds minimalistes).
Conclusion
La fonction ob_gzhandler() offre un moyen simple et autonome de compresser la sortie PHP en gzip : enregistrez-la comme callback auprès de ob_start(), et elle négocie l'encodage et définit les en-têtes pour vous. Dans les configurations modernes, cependant, la compression au niveau du serveur (Nginx, Apache) ou un CDN gérant gzip/brotli est généralement préférable — elle déleste le CPU de PHP et compresse également les ressources statiques. Connaître ob_gzhandler() reste important pour les bases de code héritées et les scripts où vous ne pouvez pas toucher la configuration du serveur. Pour une vue d'ensemble du travail avec les tampons, consultez l'aperçu PHP Output Control.