W3docs

Подробное руководство по функции mysqli_set_charset в PHP

Узнайте, как использовать mysqli_set_charset в PHP для правильной установки кодировки соединения с MySQL и защиты от SQL-инъекций.

Когда вы храните имена, комментарии или эмодзи в MySQL, байты корректно передаются туда и обратно только в том случае, если PHP и база данных согласованы по кодировке символов — отображению байтов на символы. Функция mysqli_set_charset устанавливает кодировку символов для соединения между вашим PHP-скриптом и сервером MySQL, чтобы всё отправляемое и получаемое интерпретировалось одинаково с обеих сторон.

На этой странице объясняется, что делает функция, почему важна установка кодировки для соединения (и почему это также мера безопасности), а также как её использовать с процедурным и объектно-ориентированным API mysqli.

Что делает mysqli_set_charset

mysqli_set_charset сообщает серверу MySQL, какую кодировку символов будет использовать клиент (ваш PHP-скрипт) в течение остального соединения. Это влияет на интерпретацию строк запросов, на кодировку результатов при их возврате, а также на то, какие байты mysqli_real_escape_string() считает специальными.

Процедурная сигнатура принимает соединение первым аргументом, а имя кодировки — вторым; возвращает true при успехе или false при ошибке:

mysqli_set_charset(mysqli $connection, string $charset): bool

Объектно-ориентированная форма — это метод объекта соединения:

$connection->set_charset($charset);

Аргумент $charset — это имя кодировки символов MySQL, например utf8mb4, utf8 или latin1, а не имя кодировки PHP. Используйте utf8mb4 для полной поддержки Unicode, включая 4-байтовые символы, такие как эмодзи; старый псевдоним utf8 в MySQL хранит не более 3 байт на символ и не поддерживает эмодзи.

Устанавливайте кодировку на уровне соединения, а не только в запросах. Выполнение SET NAMES utf8mb4 как запроса изменяет кодировку на стороне сервера, но не обновляет значение, которое C-библиотека клиента использует для экранирования. mysqli_set_charset обновляет оба значения — именно поэтому это правильный и безопасный способ переключения кодировок.

Подключение и установка кодировки

mysqli_set_charset требует существующего соединения, поэтому сначала откройте его с помощью mysqli_connect. В приведённом ниже примере сначала устанавливается соединение, а затем сразу задаётся utf8mb4:

<?php

$host     = 'localhost';
$user     = 'username';
$password = 'password';
$database = 'mydatabase';

$connection = mysqli_connect($host, $user, $password, $database);

if (!$connection) {
    die('Connection failed: ' . mysqli_connect_error());
}

if (!mysqli_set_charset($connection, 'utf8mb4')) {
    die('Error setting charset: ' . mysqli_error($connection));
}

echo 'Current charset: ' . mysqli_character_set_name($connection);
// Current charset: utf8mb4

После успешного вызова mysqli_character_set_name сообщает активную кодировку, подтверждая, что изменение вступило в силу.

Пример с объектно-ориентированным подходом

Если вы используете объектно-ориентированный API mysqli, вызывайте set_charset() как метод. Рекомендуется делать это сразу после создания соединения, перед выполнением любого запроса:

<?php

$mysqli = new mysqli('localhost', 'username', 'password', 'mydatabase');

if ($mysqli->connect_errno) {
    die('Connection failed: ' . $mysqli->connect_error);
}

if (!$mysqli->set_charset('utf8mb4')) {
    die('Error setting charset: ' . $mysqli->error);
}

echo $mysqli->character_set_name();
// utf8mb4

Обработка ошибок

mysqli_set_charset возвращает false, если сервер не поддерживает запрошенную кодировку (например, при опечатке вроде utf8mb44). Всегда проверяйте возвращаемое значение, не предполагая успеха:

<?php

if (!mysqli_set_charset($connection, 'utf8mb4')) {
    // Log it and stop — running queries with the wrong charset
    // can corrupt stored text and weaken escaping.
    throw new RuntimeException(
        'Failed to set charset: ' . mysqli_error($connection)
    );
}

Функцию можно вызывать несколько раз на одном соединении для смены кодировки в ходе сессии, хотя на практике её устанавливают один раз сразу после подключения и больше не меняют.

Почему это важно

  • Корректный текст. Без согласования кодировок буквы с диакритикой и нелатинские символы возвращаются как ? или кракозябры (искажённые символы вроде é вместо é).
  • Эмодзи и полный Unicode. Только utf8mb4 хранит 4-байтовые символы; utf8 молча теряет или усекает их.
  • Безопасность. mysqli_real_escape_string() выполняет экранирование в зависимости от кодировки соединения. Правильная установка кодировки закрывает класс векторов SQL-инъекций, эксплуатирующих несоответствие многобайтовых кодировок. Тем не менее предпочтительнее использовать подготовленные выражения вместо ручного экранирования.

Связанные функции

  • mysqli_connect — открыть соединение, передаваемое в set_charset.
  • mysqli_get_charset — получить полный объект с описанием текущей кодировки (сопоставление, комментарий, номер).
  • mysqli_character_set_name — получить только имя активной кодировки.
  • mysqli_select_db — переключить активную базу данных на существующем соединении.

Заключение

mysqli_set_charset согласует кодировку символов вашего PHP-скрипта с MySQL-соединением, обеспечивая корректную передачу текста в обоих направлениях и безопасное экранирование. Установите значение utf8mb4 сразу после подключения, проверьте возвращаемое значение — и вы охватите типичные случаи: от имён с акцентами до эмодзи.

Практика

Практика
Какой вызов правильно устанавливает кодировку соединения для полного Unicode и является рекомендуемым?
Какой вызов правильно устанавливает кодировку соединения для полного Unicode и является рекомендуемым?
Was this page helpful?