Mb output handler: примеры (PHP)
mb_output_handler(string $string, int $status): stringmb_output_handler — это функция-обратный вызов (callback) для ob_start(). Она предназначена для преобразования кодировки символов в выходном буфере.
Функция используется, когда необходимо динамически конвертировать кодировку выводимых данных, например, из внутренней кодировки скрипта (например, UTF-8) в кодировку, которую ожидает браузер пользователя (например, windows-1251). Это особенно полезно для приложений с поддержкой множества языков.
Функция принимает два обязательных аргумента:
- string $contents — содержимое выходного буфера.
- 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();
?>Завершено: Тестовый контент
- 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).
<?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
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
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!'
Используются 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';