Кодировка UTF-8 в PHP: практическое применение и тонкости

Раздел: Веб-разработка на PHP -> Кодировка в PHP

Настройка charset UTF-8 в PHP: варианты и рекомендации

Как обеспечить корректную работу с UTF-8 на всех этапах обработки данных в PHP?

Наиболее полное и рекомендуемое решение - задать кодировку UTF-8 на всех уровнях: в HTTP-заголовках, в самом скрипте, в соединении с базой данных и в файлах. Это позволяет избежать большинства проблем с отображением и обработкой многобайтовых символов.


// Устанавливаем внутреннюю кодировку и HTTP-вывод
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');

// Отправляем заголовок Content-Type
header('Content-Type: text/html; charset=utf-8');

// Если сессия - также кодировка
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}
  

Php charset utf 8 (charset utf-8 в php)

Типичные ошибки:

  • Забыли вызвать mb_internal_encoding - функции strlen, substr работают неверно.
  • Не задан заголовок Content-Type - браузер может интерпретировать страницу в другой кодировке.
  • В php.ini не включено расширение mbstring - все mb_* функции недоступны.

Решение:

Проверить наличие расширения, настроить php.ini:


; php.ini
extension=mbstring
; или в Windows: extension=php_mbstring.dll

; Также можно указать значения по умолчанию
mbstring.internal_encoding = UTF-8
mbstring.http_output = UTF-8
    

Что делать, если нет возможности менять php.ini или расширение mbstring отключено?

Можно обойтись только HTTP-заголовками и функциями iconv для преобразования строк. Однако такой подход менее удобен, так как отсутствуют специализированные многобайтовые функции.


// Альтернатива без mbstring
header('Content-Type: text/html; charset=utf-8');

// Для работы с подстроками используем iconv_substr вместо mb_substr
$string = 'Привет, мир!';
// iconv_substr - если нужен только срез
$sub = iconv_substr($string, 0, 6, 'UTF-8');
echo $sub; // 'Привет'
  

Проблема: iconv может не поддерживать все необходимые операции (например, замену в строке).

Решение: Установка mbstring через пакетный менеджер или сборка PHP с поддержкой многобайтовых строк.

Как настроить соединение с базой данных MySQL на UTF-8?

При использовании PDO:


$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$pdo = new PDO($dsn, 'user', 'password');
$pdo->exec('SET NAMES utf8'); // дополнительная страховка
  

Для mysqli:


$mysqli = new mysqli('localhost', 'user', 'password', 'test');
$mysqli->set_charset('utf8');
  

Ошибка: использование SET NAMES utf8 без соответствующей кодировки в DSN может привести к двойной конвертации.

Решение: Применять charset=utf8 в DSN или set_charset - они эквивалентны.

Как обрабатывать JSON с UTF-8 в PHP?

Функции json_encode и json_decode корректно работают с UTF-8, если входные строки уже в UTF-8. Необходимо убедиться, что данные закодированы в UTF-8 до вызова.


$data = ['name' => 'Иван', 'city' => 'Москва'];
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
echo $json; // {"name":"Иван","city":"Москва"}
  

Проблема: Если исходные строки не UTF-8, JSON будет некорректным или вызовет ошибку.

Решение: Перед кодированием преобразовывать данные в UTF-8 с помощью iconv или mb_convert_encoding.

Как обрабатывать файлы и сохранять их в UTF-8 без BOM?

При записи в файл используйте fwrite с предварительным преобразованием строки в UTF-8. Для чтения можно проверить BOM и удалить его.


// Удаление BOM при чтении
$content = file_get_contents($file);
$bom = pack('H*','EFBBBF');
if (strncmp($content, $bom, 3) === 0) {
    $content = substr($content, 3);
}
  

Ошибка: BOM может вызывать проблемы при обработке JSON или XML.

Решение: Сохранять файлы всегда в UTF-8 без BOM (например, в редакторе выбирать опцию UTF-8 without BOM).

Расширенные примеры работы с UTF-8 в PHP

Приведённые ниже примеры показывают типовые ситуации и продвинутые приёмы.

1. Многобайтовые строковые функции

Пример

$text = 'Привет, мир!';

// Длина в байтах и символах
echo strlen($text) . '\n';          // 19 (количество байт)
echo mb_strlen($text, 'UTF-8') . '\n';  // 12 (количество символов)

// Подстрока
echo substr($text, 0, 6) . '\n';         // 'Приве' (обрезано некорректно)
echo mb_substr($text, 0, 6, 'UTF-8') . '\n'; // 'Привет'

// Поиск позиции
echo strpos($text, 'мир') . '\n';        // 11 (байтовая позиция)
echo mb_strpos($text, 'мир', 0, 'UTF-8') . '\n'; // 7 (символьная)
19
12
Приве
Привет
11
7

2. Регулярные выражения с Unicode

Пример

$text = 'Привет, мир!';

// Поиск всех буквенных символов
preg_match_all('/\p{L}+/u', $text, $matches);
print_r($matches[0]);
// Результат: Array ( [0] => Привет [1] => мир )

// Удаление знаков препинания
$clean = preg_replace('/\p{P}/u', '', $text);
echo $clean; // 'Привет мир'
Array
(
    [0] => Привет
    [1] => мир
)
Привет мир

3. Преобразование кодировок из windows-1251 в UTF-8

Пример

$text = 'Привет';
$cp1251 = iconv('UTF-8', 'windows-1251//IGNORE', $text);
// или
$cp1251 = mb_convert_encoding($text, 'windows-1251', 'UTF-8');

// Обратно
$utf8 = iconv('windows-1251', 'UTF-8//IGNORE', $cp1251);
echo $utf8; // 'Привет'

4. Проверка валидности UTF-8 строки

Пример

function is_valid_utf8($string) {
    return mb_check_encoding($string, 'UTF-8');
}

$good = 'Привет';
$bad = "\xff\xfe"; // некорректная последовательность
echo is_valid_utf8($good) ? 'valid' : 'invalid'; // valid
echo is_valid_utf8($bad) ? 'valid' : 'invalid'; // invalid
valid
invalid

5. Работа с массивом строк: сортировка и преобразование

Пример

$names = ['Иван', 'Анна', 'Борис'];

// Сортировка с учётом локали (зависит от локали системы)
setlocale(LC_COLLATE, 'ru_RU.UTF-8');
usort($names, 'strcoll');
print_r($names); // ['Анна', 'Борис', 'Иван']

// Преобразование всех ключей массива в UTF-8 (рекурсивно)
function utf8ize($mixed) {
    if (is_array($mixed)) {
        return array_map('utf8ize', $mixed);
    } else if (is_string($mixed)) {
        return mb_convert_encoding($mixed, 'UTF-8', mb_detect_encoding($mixed, 'UTF-8, windows-1251, ISO-8859-1', true));
    }
    return $mixed;
}

$data = ['name' => 'Привет'];
$converted = utf8ize($data);
Array
(
    [0] => Анна
    [1] => Борис
    [2] => Иван
)

6. Чтение файла с неизвестной кодировкой и конвертация

Пример

$content = file_get_contents('somefile.txt');
$detect = mb_detect_encoding($content, 'UTF-8, windows-1251, KOI8-R', true);
if ($detect && $detect !== 'UTF-8') {
    $content = mb_convert_encoding($content, 'UTF-8', $detect);
}
echo $content;

7. Отправка email с UTF-8 заголовками

Пример

$subject = 'Привет из PHP';
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/plain; charset=utf-8' . "\r\n";
$headers .= 'From: sender@example.com' . "\r\n";

// Кодирование темы по RFC 2047
$subject = '=?UTF-8?B?' . base64_encode($subject) . '?=';

mail('user@example.com', $subject, 'Тело письма', $headers);

8. Защита от ошибок при использовании mb_* функций

Пример

// Проверка доступности расширения
if (!extension_loaded('mbstring')) {
    // fallback на iconv или самостоятельные реализации
}

// Для совместимости с PHP < 5.4 можно определить свою версию mb_strlen
if (!function_exists('mb_strlen')) {
    function mb_strlen($string, $encoding = 'UTF-8') {
        return strlen(iconv($encoding, 'UTF-16', $string)) / 2;
    }
}

Charset UTF-8 в PHP - comments

En
Php charset utf 8 (php)