UTF-8 на всём пути: как настроить PHP, MySQL и веб-сервер для корректной работы с кириллицей и Юникодом
Полное руководство по настройке UTF-8 в PHP, MySQL и Apache
Проблема, с которой вы столкнулись, классическая для начинающих разработчиков. Суть фразы «UTF-8 all the way through» (или «Юникод на всём пути») в том, что кодировка UTF-8 должна быть установлена на каждом этапе обработки данных: от браузера пользователя до базы данных и обратно. Если хотя бы один этап работает в другой кодировке (например, Windows-1251 или Latin1), данные искажаются.
Вот пошаговая инструкция, как исправить ситуацию раз и навсегда.
1. Настройка HTML-страницы
Убедитесь, что в <head> вашего HTML-шаблона указана правильная мета-информация:
<meta charset="UTF-8">
Или, если вы используете XHTML:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
2. Настройка PHP
В начале каждого PHP-скрипта (или в общем файле конфигурации) добавьте:
<?php
// Отправляем правильный HTTP-заголовок
header('Content-Type: text/html; charset=UTF-8');
// Устанавливаем внутреннюю кодировку для многобайтовых строк
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
// Если используете функции вроде substr(), strpos() — используйте их mb_* версии
?>
3. Настройка соединения с MySQL
Это самая частая ошибка. После подключения к БД, но до выполнения любых запросов, установите кодировку соединения:
<?php
$db = new mysqli('localhost', 'user', 'pass', 'mydb');
// Проверяем соединение
if ($db->connect_error) {
die('Ошибка подключения: ' . $db->connect_error);
}
// Устанавливаем кодировку соединения UTF-8
$db->set_charset('utf8mb4'); // ВАЖНО: используйте utf8mb4, а не utf8!
// Или через запрос:
// $db->query("SET NAMES 'utf8mb4'");
?>
Почему utf8mb4? Потому что стандартный utf8 в MySQL поддерживает только 3 байта на символ (не хватает для эмодзи и некоторых редких иероглифов). utf8mb4 — полная 4-байтовая версия UTF-8.
4. Настройка базы данных и таблиц
При создании базы данных и таблиц используйте правильную кодировку и сравнение:
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Если таблицы уже существуют, их можно изменить:
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
5. Настройка Apache (веб-сервера)
В файле .htaccess или в конфигурации виртуального хоста добавьте:
AddDefaultCharset UTF-8
Или в PHP-файлах:
php_value default_charset UTF-8
6. Ваш исправленный код
<?php
header('Content-Type: text/html; charset=UTF-8');
mb_internal_encoding('UTF-8');
$db = new mysqli('localhost', 'user', 'pass', 'mydb');
if ($db->connect_error) {
die('Ошибка: ' . $db->connect_error);
}
// Ключевая строка:
$db->set_charset('utf8mb4');
$name = $_POST['name']; // В реальном проекте — экранируйте!
$stmt = $db->prepare("INSERT INTO users (name) VALUES (?)");
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $db->query("SELECT name FROM users");
while ($row = $result->fetch_assoc()) {
echo htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8');
}
?>
Что ещё проверить?
- Редактор кода: Убедитесь, что ваш PHP-файл сохранён в кодировке UTF-8 (без BOM). В VS Code, PhpStorm, Sublime это настраивается внизу окна.
- Формы: У форм тоже должен быть атрибут
accept-charset="UTF-8"(хотя современные браузеры по умолчанию используют кодировку страницы). - JSON: При работе с JSON используйте
json_encode($data, JSON_UNESCAPED_UNICODE). - Файлы: Если читаете/пишете файлы, используйте
fopen()с указанием кодировки илиfile_get_contents().
После этих настроек русские буквы, эмодзи и любые символы Юникода будут корректно проходить весь путь: браузер → PHP → MySQL → PHP → браузер.
<<Альтернативный подход: использование PDO и глобальных настроек
Если вы предпочитаете PDO вместо mysqli, вот как настроить UTF-8 в этом случае:
<?php
header('Content-Type: text/html; charset=UTF-8');
$dsn = 'mysql:host=localhost;dbname=mydb;charset=utf8mb4';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4'"
];
try {
$db = new PDO($dsn, 'user', 'pass', $options);
} catch (PDOException $e) {
die('Ошибка подключения: ' . $e->getMessage());
}
// Теперь все запросы будут в UTF-8
$name = $_POST['name'];
$stmt = $db->prepare("INSERT INTO users (name) VALUES (?)");
$stmt->execute([$name]);
$result = $db->query("SELECT name FROM users");
foreach ($result as $row) {
echo htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8');
}
?>
Также рекомендую проверить php.ini — там можно установить глобальные значения:
default_charset = "UTF-8"
mbstring.internal_encoding = UTF-8
mbstring.http_output = UTF-8
mbstring.func_overload = 0
И не забывайте про htmlspecialchars() при выводе данных — это защитит от XSS-атак и гарантирует правильное отображение спецсимволов.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги