Mb output handler: примеры (PHP)

Функция mb_output_handler для работы с многобайтовыми кодировками
Раздел: Многобайтовые строки
mb_output_handler(string $string, int $status): string
mb_output_handler: определение и параметры

mb_output_handler — это функция-обратный вызов (callback) для ob_start(). Она предназначена для преобразования кодировки символов в выходном буфере.

Функция используется, когда необходимо динамически конвертировать кодировку выводимых данных, например, из внутренней кодировки скрипта (например, UTF-8) в кодировку, которую ожидает браузер пользователя (например, windows-1251). Это особенно полезно для приложений с поддержкой множества языков.

Аргументы функции

Функция принимает два обязательных аргумента:

  1. string $contents — содержимое выходного буфера.
  2. int $status — статус буфера (битовая маска флагов). Флаги: PHP_OUTPUT_HANDLER_START (буфер запущен), PHP_OUTPUT_HANDLER_CONT (буфер продолжается) и PHP_OUTPUT_HANDLER_END (буфер завершен).

Функция возвращает преобразованную строку.

Краткие примеры использования

Установка внутренней кодировки скрипта и кодировки для вывода. Затем функция используется как обработчик буферизации.

<?php
mb_internal_encoding('UTF-8');
mb_http_output('windows-1251');

ob_start('mb_output_handler');

echo 'Привет, мир! Текст в UTF-8.';

ob_end_flush(); // Выведет текст, преобразованный в windows-1251
?>
Привет, мир! Текст в UTF-8.

Проверка статуса буфера внутри обработчика.

<?php
mb_internal_encoding('UTF-8');
mb_http_output('ISO-8859-5');

function custom_handler($contents, $status) {
    if ($status & PHP_OUTPUT_HANDLER_END) {
        return 'Завершено: ' . mb_convert_encoding($contents, 'ISO-8859-5', 'UTF-8');
    }
    return mb_convert_encoding($contents, 'ISO-8859-5', 'UTF-8');
}

ob_start('custom_handler');
echo 'Тестовый контент';
ob_end_flush();
?>
Завершено: Тестовый контент
Похожие функции в PHP
  • mb_convert_encoding() — напрямую преобразует строку из одной кодировки в другую. Предпочтительнее для точечного преобразования конкретных строк, а не всего вывода.
  • iconv() — функция из расширения iconv для конвертации кодировок. Часто обладает большей производительностью для некоторых кодировок. Выбор между mb_* и iconv зависит от конкретной кодировки и потребностей.
  • ob_start() с пользовательской callback-функцией — позволяет создать свой обработчик вывода для любых манипуляций, не только конвертации кодировки.
  • Настройка веб-сервера (например, Apache с mod_charset_lite) — альтернатива на уровне сервера для статической конвертации контента.

Использование mb_output_handler оправдано, когда нужно централизованно управлять кодировкой всего HTML-вывода скрипта.

Типичные ошибки
Несовпадение или неверная настройка кодировок

Если mb_internal_encoding или mb_http_output не установлены, функция может работать некорректно.

<?php
// ВНИМАНИЕ: Внутренняя кодировка не установлена. Предположим, скрипт в UTF-8.
mb_http_output('windows-1251');
ob_start('mb_output_handler');
echo 'Тест';
ob_end_flush(); // Может вывести искаженные символы, если исходная кодировка не UTF-8.
?>
Использование с бинарным контентом

Попытка преобразовать бинарные данные (например, изображение) приведет к их порче.

<?php
mb_internal_encoding('UTF-8');
mb_http_output('windows-1251');
ob_start('mb_output_handler');
header('Content-Type: image/jpeg');
echo file_get_contents('image.jpg'); // Файл будет испорчен!
ob_end_flush();
?>

Для исправления необходимо отключать обработчик для бинарного вывода или проверять тип контента.

История изменений функции

Функция mb_output_handler появилась в PHP 4.0.6. Значительных изменений в её поведении в последних основных версиях PHP (7.x, 8.x) не было. Функция продолжает стабильно работать как callback для ob_start().

Важные моменты:

  • Стандартная реализация всегда учитывает настройки, установленные mb_internal_encoding() и mb_http_output().
  • В PHP 8.x, как и в более ранних версиях, функция ожидает, что внутренняя кодировка является одной из поддерживаемых многобайтовых кодировок (предпочтительно UTF-8).
Расширенные примеры применения
Динамическое переключение кодировки вывода на основе заголовка Accept-Charset
Пример php
<?php
mb_internal_encoding('UTF-8');

// Упрощенное определение предпочтительной кодировки клиента
$clientCharset = 'UTF-8'; // По умолчанию
if (strpos($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '', 'windows-1251') !== false) {
    $clientCharset = 'windows-1251';
}

mb_http_output($clientCharset);
ob_start('mb_output_handler');
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset='<?php echo $clientCharset; ?>'>
</head>
<body>
    <p>Страница адаптирована под вашу кодировку.</p>
</body>
</html>
<?php
ob_end_flush();
?>
Многоуровневая буферизация с конвертацией

Использование вложенных буферов, где только один обрабатывает кодировку.

Пример php
<?php
mb_internal_encoding('UTF-8');
mb_http_output('KOI8-R');

// Первый буфер для сжатия (если доступно)
ob_start('ob_gzhandler');
// Второй буфер для конвертации кодировки
ob_start('mb_output_handler');

echo 'Контент в UTF-8, но будет отправлен в KOI8-R и сжат.';

ob_end_flush(); // Завершает буфер конвертации
ob_end_flush(); // Завершает буфер сжатия и отправляет клиенту
?>
Логирование содержимого буфера перед отправкой
Пример php
<?php
mb_internal_encoding('UTF-8');
mb_http_output('windows-1251');

function handler_with_log($contents, $status) {
    // Логируем исходный размер (в байтах)
    error_log('Буфер: ' . strlen($contents) . ' байт до конвертации.');
    // Стандартное преобразование
    $converted = mb_convert_encoding($contents, mb_http_output(), mb_internal_encoding());
    // Логируем статус
    if ($status & PHP_OUTPUT_HANDLER_END) {
        error_log('Буферизация завершена.');
    }
    return $converted;
}

ob_start('handler_with_log');
echo 'Тест логирования';
ob_end_flush();
?>
Аналоги в других языках

Mb output handler в Python

Используются codecs или строковые методы encode/decode. Прямого аналога обработчика буфера нет, преобразование явное.

# Внутреннее представление (Unicode)
text = 'Привет, мир!'
# Явное преобразование при выводе
encoded_text = text.encode('cp1251')
print(encoded_text) # Для вывода в байтах
# Или для записи в файл
with open('file.txt', 'w', encoding='cp1251') as f:
    f.write(text)
b'\xcf\xf0\xe8\xe2\xe5\xf2, \xec\xe8\xf0!'
JavaScript (Node.js)

Используются Buffer и TextDecoder/TextEncoder.

// Преобразование строки в буфер с нужной кодировкой
const encoder = new TextEncoder(); // По умолчанию UTF-8
const decoder = new TextDecoder('windows-1251');

const utf8Buffer = encoder.encode('Привет');
console.log(utf8Buffer); // Байты UTF-8

const win1251Buffer = Buffer.from('Привет', 'windows-1251');
console.log(win1251Buffer); // Байты windows-1251
console.log(decoder.decode(win1251Buffer)); // Обратно в строку
<Buffer d0 9f d1 80 d0 b8 d0 b2 d0 b5 d1 82>
<Buffer cf f0 e8 e2 e5 f2>
Привет

Mb output handler в MySQL

Преобразование кодировки для результатов запроса с помощью CONVERT или CAST, либо настройка кодировки соединения.

-- Конвертация поля в другую кодировку в запросе
SELECT CONVERT(column_name USING cp1251) FROM table;

-- Установка кодировки соединения
SET NAMES 'cp1251';

PHP mb_output_handler function comments

En
Mb output handler Callback function converts character encoding in output buffer