Ob gzhandler: примеры (PHP)
ob_gzhandler(string $data, int $flags): string|falseФункция ob_gzhandler
Функция ob_gzhandler предназначена для использования в качестве callback-обработчика буферизации вывода (ob_start()). Она сжимает содержимое буфера, используя сжатие GZIP или DEFLATE, перед его отправкой браузеру, если клиент поддерживает такой формат.
Использование целесообразно для уменьшения объёма передаваемых по сети HTML, CSS или JavaScript данных, что ускоряет загрузку страницы.
- string $data (обязательный) — содержимое буфера вывода, которое требуется обработать.
- int $flags (опциональный) — битовая маска, управляющая режимом работы. Возможные значения:
PHP_OUTPUT_HANDLER_START,PHP_OUTPUT_HANDLER_CONTиPHP_OUTPUT_HANDLER_END. Обычно передаётся автоматически механизмом буферизации.
Функция возвращает сжатые (если клиент поддерживает) или исходные данные. В случае неудачи возвращает false.
Короткие примеры использования
Включение буферизации с обработчиком ob_gzhandler:
<?php
// Включение буферизации с gzip-сжатием
ob_start('ob_gzhandler');
echo str_repeat('Пример контента для сжатия. ', 100);
ob_end_flush();
?>// Вывод в браузере будет сжат (проверить можно через инструменты разработчика во вкладке Network, колонка Content-Encoding: gzip).
// Исходный текст будет передан в сжатом виде.
<?php
// Функция сама проверяет заголовки Accept-Encoding от клиента
ob_start('ob_gzhandler');
echo 'Контент';
ob_end_flush();
?>// Если браузер поддерживает gzip/deflate, контент будет сжат.
// Если нет (например, старый браузер), будет передан как есть.
Похожие функции в PHP
- ob_start() с пользовательской функцией: Позволяет создать собственный обработчик для манипуляций с буфером (например, для минификации). Более гибкий, но требует написания кода для сжатия.
- Включение сжатия через zlib.output_compression в php.ini: Директива
zlib.output_compression = Onглобально включает сжатие вывода для всех скриптов. Работает на более низком уровне, чем ob_gzhandler, и часто более эффективна, так как не требует явного вызоваob_startв коде. Если включено, использовать ob_gzhandler не нужно (может привести к конфликту). - gzencode() / gzdeflate(): Функции для явного сжатия строк. Используются, когда нужно сжать конкретные данные, а не весь вывод скрипта.
Предпочтение стоит отдать настройке zlib.output_compression в конфигурации сервера для глобального сжатия. Функция ob_gzhandler полезна, когда требуется точечное управление сжатием на уровне отдельных скриптов или когда нет доступа к изменению php.ini.
Аналоги в других языках и системах
from flask import Flask, Response
import gzip
import io
app = Flask(__name__)
@app.route('/')
def index():
content = 'Пример контента ' * 100
# Проверяем заголовок Accept-Encoding и сжимаем при необходимости вручную
# Или используем middleware, например, Flask-Compress
return Response(content)Особенность: В Python сжатие обычно настраивается на уровне WSGI-сервера (Gunicorn, uWSGI) или через middleware, а не внутри обработчика view-функции, что ближе к настройке zlib в PHP.
const express = require('express');
const compression = require('compression'); // middleware
const app = express();
app.use(compression()); // Глобальное подключение middleware сжатия
app.get('/', (req, res) => {
res.send('Пример контента '.repeat(100));
});Особенность: Сжатие реализуется как промежуточное ПО (middleware), что концептуально похоже на обработчик буфера в PHP, но интегрировано в поток обработки запроса фреймворка.
# Конфигурация Nginx
gzip on;
gzip_types text/html text/css application/javascript;Особенность: Сжатие происходит на уровне веб-сервера, полностью независимо от языка программирования backend'а. Это наиболее эффективный и рекомендуемый подход для продакшена, так как разгружает PHP-процессы.
Типичные ошибки
<?php
ob_start('ob_gzhandler');
echo 'Некоторый вывод...';
// Попытка отправить заголовок после того, как вывод уже начал обрабатываться буфером
header('X-Custom-Header: Value');
ob_end_flush();
?>Warning: Cannot modify header information - headers already sent by ...
Решение: Убедиться, что все вызовы header(), setcookie() и т.п. происходят до любого вывода и до вызова ob_start().
<?php
// В php.ini: zlib.output_compression = On
// А в коде:
ob_start('ob_gzhandler'); // Ошибка!
?>Результат: Может привести к битым данным или ошибкам. Нужно использовать что-то одно: либо глобальную настройку zlib, либо обработчик.
<?php
ob_start('ob_gzhandler');
header('Content-Type: image/jpeg');
readfile('image.jpg'); // Изображение уже сжато
ob_end_flush();
?>Результат: Изображение может быть испорчено, так как формат JPEG уже сжат. Функция предназначена в первую очередь для текстовых данных.
Изменения в последних версиях PHP
В PHP 8.0 существенных изменений в поведении функции ob_gzhandler не было. Основная логика работы осталась прежней.
Важное изменение, касающееся контекста сжатия, произошло в более ранних версиях: улучшена интеграция с расширением Zlib. Рекомендуется использовать актуальную версию PHP для лучшей производительности и безопасности.
В целом, развитие PHP смещается в сторону более глобальных настроек (таких как zlib.output_compression) и делегирования задач сжатия обратному прокси (Nginx, Apache mod_deflate).
Расширенные и специальные примеры
<?php
function processBuffer($buffer) {
// Сначала минифицируем HTML (упрощённый пример)
$buffer = preg_replace('/\s+/', ' ', $buffer);
// Затем передаём на сжатие стандартному обработчику
return ob_gzhandler($buffer, PHP_OUTPUT_HANDLER_END);
}
ob_start('processBuffer');
?>
<html>
<body>
<h1> Тест </h1>
</body>
</html>
<?php
ob_end_flush();
?>// Браузер получит минифицированный и сжатый HTML.
<?php
function smartGzHandler($buffer, $flags) {
// Сжимаем только если контент большой и текстовый
if (strlen($buffer) > 1024 &&
stripos($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '', 'gzip') !== false) {
return ob_gzhandler($buffer, $flags);
}
return $buffer;
}
ob_start('smartGzHandler');
// ... вывод контента
?>Функция ob_gzhandler не позволяет задать уровень сжатия. Для этого нужно использовать собственную реализацию на основе gzencode():
<?php
function myGzHandler($buffer, $flags, $level = 6) {
if (headers_sent() || connection_aborted()) {
return $buffer;
}
$encoding = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '';
if (strpos($encoding, 'gzip') !== false) {
header('Content-Encoding: gzip');
return gzencode($buffer, $level);
} elseif (strpos($encoding, 'deflate') !== false) {
header('Content-Encoding: deflate');
return gzdeflate($buffer, $level);
}
return $buffer;
}
ob_start('myGzHandler');
echo 'Контент для сжатия с заданным уровнем.';
ob_end_flush();
?>// Контент будет сжат с уровнем 6 (по умолчанию в gzencode).