Función PHP ob_gzhandler(): Todo lo que necesitas saber
Aprende a usar ob_gzhandler() en PHP para comprimir la salida con gzip, reducir el ancho de banda y mejorar la velocidad de carga de tu sitio web.
Comprimir HTML, CSS o JSON antes de que salga del servidor reduce el ancho de banda y hace que las páginas carguen más rápido. La función integrada ob_gzhandler() de PHP es una forma lista para usar esto desde dentro de tu script: se la pasas al búfer de salida y comprime con gzip todo lo que tu script imprime, pero solo cuando el navegador indica que puede descomprimirlo. Este artículo cubre su sintaxis, un ejemplo completo, cómo negocia con el cliente, los errores comunes y cuándo deberías usarla frente a dejar que el servidor gestione la compresión.
Qué hace la función ob_gzhandler()
ob_gzhandler() es un callback diseñado para pasarse a ob_start(). Nunca se llama directamente — en cambio, el sistema de búfer de salida la invoca con el contenido del búfer como argumento, y devuelve los bytes comprimidos (o, cuando la compresión no es posible, sin modificar).
Antes de comprimir, inspecciona la cabecera Accept-Encoding de la solicitud y elige el esquema mejor soportado:
- Si el cliente soporta gzip, comprime con gzip y establece
Content-Encoding: gzip. - Si el cliente solo soporta deflate, usa deflate en su lugar.
- Si el cliente no soporta ninguno, devuelve el contenido sin cambios y
ob_start()falla (devuelvefalse), por lo que la respuesta se envía sin comprimir.
Como establece las cabeceras de respuesta Content-Encoding y Vary automáticamente, debes registrarla antes de que se envíe cualquier salida — consulta headers_sent() si encuentras un error de "cabeceras ya enviadas".
Sintaxis
ob_start("ob_gzhandler");ob_gzhandler() acepta dos parámetros internamente ($buffer y $mode), pero nunca los proporcionas tú — los suministra el motor de búfer. Solo registras la cadena "ob_gzhandler" como nombre del callback.
Un ejemplo completo
<?php
ob_start("ob_gzhandler");
echo "This will be compressed using gzip compression";
ob_end_flush();
?>Aquí, ob_start() abre un búfer de salida con ob_gzhandler() como su manejador, el echo escribe en ese búfer en lugar de directamente al cliente, y ob_end_flush() cierra el búfer y envía su contenido (ahora comprimido). Desde el punto de vista del visitante nada cambia — el navegador descomprime la respuesta de forma transparente — pero se transfieren menos bytes por la red.
Alternativa para clientes que no soportan gzip
ob_start("ob_gzhandler") devuelve false cuando el cliente no anuncia soporte para gzip o deflate. Si ignoras eso, no se inicia ningún búfer y tu posterior ob_end_flush() generará una advertencia. Comprueba el valor de retorno y recurre a un búfer 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();
?>Ajustar el nivel de compresión
ob_start() no acepta un nivel de compresión — ob_gzhandler() usa el valor predeterminado de zlib (controlado por el parámetro INI zlib.output_compression_level, por defecto -1). Para forzar un nivel específico del 1 (más rápido, menos compresión) al 9 (más lento, mayor compresión), omite ob_gzhandler() y usa tu propio callback con gzencode():
<?php
ob_start(function ($buffer) {
return gzencode($buffer, 9);
});
echo "Compressed at the maximum level.";
ob_end_flush();
?>Ten en cuenta que este callback personalizado no negocia Accept-Encoding ni establece Content-Encoding: gzip por ti — ob_gzhandler() hace ambas cosas automáticamente. Si creas el tuyo propio, debes enviar esas cabeceras tú mismo, razón por la que ob_gzhandler() sigue siendo conveniente para el caso habitual.
ob_gzhandler() frente a zlib.output_compression
PHP ofrece una segunda forma, incluso más sencilla, de comprimir la salida: la directiva INI zlib.output_compression. Establécela en On (o un umbral en bytes) y PHP comprimirá toda la respuesta con gzip sin ningún código adicional:
zlib.output_compression = OnLos dos enfoques son mutuamente excluyentes — habilitar zlib.output_compression mientras también se llama a ob_start("ob_gzhandler") genera una advertencia y la doble compresión no produce nada útil. Prefiere zlib.output_compression cuando puedas editar php.ini o usar ini_set(), y reserva ob_gzhandler() para los casos en que lo necesites dentro de un script sobre cuya configuración no tienes control.
Errores comunes
- No anides capas gzip. Combinar
ob_gzhandler()con compresión a nivel de servidor (Nginx/Apachegzip) o conzlib.output_compressionpuede producir respuestas corruptas con doble codificación. - Regístralo primero. Cualquier
echoprevio, espacio en blanco antes de<?phpo BOM en el archivo envía las cabeceras anticipadamente y rompe la compresión. - No para datos binarios ya comprimidos. Comprimir con gzip archivos JPEG, PNG o ZIP malgasta CPU con casi ninguna ventaja de tamaño.
- Requiere la extensión zlib.
ob_gzhandler()necesita que PHP esté compilado con zlib (casi siempre lo está, pero vale la pena saberlo en compilaciones mínimas).
Conclusión
La función ob_gzhandler() proporciona una forma sencilla y autocontenida de comprimir la salida PHP con gzip: regístrala como callback en ob_start() y negociará la codificación y establecerá las cabeceras por ti. En configuraciones modernas, sin embargo, generalmente se prefiere la compresión a nivel de servidor (Nginx, Apache) o un CDN que gestione gzip/brotli — descarga la CPU de PHP y también comprime los activos estáticos. Conocer ob_gzhandler() sigue siendo importante para bases de código heredadas y scripts donde no puedes tocar la configuración del servidor. Para una visión más amplia del trabajo con búferes, consulta el resumen de Control de salida de PHP.