Как избежать проблем с кодировками

Представьте себе на минутку, что идет беседа между шотландцем и китайцем, только шотландец не знает китайского, а китаец не знает английского, но есть переводчик, который знает оба языка. Шотландец рассказывает историю на своем диалектном английском. Переводчик пытается максимально точно передать суть китайцу, но, увы, он никогда не был в Шотландии, и не догадывается о том, что там многие, привычные ему слова, имеют совершенно другие значения. Наверное, Вы уже догадались, что далее беседа превращается в испорченный телефон…

А теперь представьте, что шотландец это кодировка latin1, а его диалект — это сопоставление swedish_ci. Переводчик, это соответственно та же latin1 только уже general_ci, но он не знает, что сопоставление шотландца — это swedish_ci. Ну а китаец — это utf-8 с сопоставлением unicode_ci, и ему все равно, кто такой шотландец и даже, кто такой переводчик, он уверен, что с ним общаются на его родном utf-8 в unicode_ci. И теперь начинается самое интересное: шотландец говорит переводчику: «Скажи, пожалуйста, китайцу следующее в utf8_unicode_ci…», переводчик внимательно слушает шотландца и переводит с latin1_general_ci в utf8_general_ci, и вроде все хорошо, но ведь должно быть немного не так, переводчик должен был перевести с latin1_swedish_ci в utf8_unicode_ci, а этого не произошло. А теперь представьте, что будет, если из этого трио уйдет переводчик. Да, будет именно то, что мы называем иероглифами, знаками вопроса или кракозябрами. К счастью, этого можно избежать.

Теперь отступим от аналогий и сравнений и углубимся в суть. У MySQL сервера есть некие GLOBAL VARIABLES, или просто глобальные переменные, среди которых есть те, которые отвечают за кодировки. Сервер обращается к этим переменным в том случае, когда ему не указали, в какой кодировке и с каким сопоставлением он должен общаться с клиентом — скриптом. В какой кодировке приходят данные от скрипта, в какую кодировку их перекодировать, чтобы записать в БД, а в какой кодировке их отдать скрипту, если это понадобится? Каждая из этих переменных может хранить только одно значение, ведь всем пользовательским БД на сервере не угодить, у кого-то БД использует cp1251, у кого-то utf-8, а у кого-то вообще latin1, поэтому настоятельно рекомендуется после инициализации соединения с БД указывать серверу, в какой кодировке мы хотим отправлять, хранить и читать наши данные, даже, если эта кодировка совпадает с кодировкой по умолчанию. И так, что для этого нужно. Нужно знать только кодировку таблиц Вашей БД (берем тот случай, когда заведомо известно, что данные в таблицах хранятся в той же кодировке, что и сами таблицы, и кодировка БД выставлена верно). Открываем скрипт инициализации соединения с БД и сразу после установки соединения добавляем следующую строку:

mysql_query(«SET CHARACTER SET ‘X'»);

где, X — кодировка ваших таблиц без сопоставления.

Этот запрос сделает следующее, он установит:

SET character_set_client = X;
SET character_set_results = X;
SET character_set_connection = кодировка Вашей БД;
SET collation_connection = сопоставление(сравнение) таблиц Вашей БД;

Либо так:

mysql_query(«SET NAMES ‘X’ COLLATE Y»»);

где, X и Y — кодировка БД и сопоставление(сравнение) таблиц БД соответственно.

А этот запрос, сделает тоже, что и предыдущий, только сопоставление здесь Вы указываете самостоятельно:

SET character_set_client = X;
SET character_set_results = X;
SET character_set_connection = X;
SET collation_connection = Y;

Теперь рассмотрим подробно, для чего нужна каждая из переменных.

character_set_client — указывает, в какой кодировке клиент (скрипт) передает данные серверу.
Примечание: если скрипт самостоятельно не конвертирует данные, то значение этой переменной и charset мета тега должны совпадать:

meta http-equiv=»Content-Type» content=»text/html; charset=X»

character_set_results — указывает, в какой кодировке сервер будет отдавать данные из БД клиенту (скрипту).

character_set_connection — указывает в какую кодировку нужно перекодировать присланные клиентом данные из кодировки, указанной в character_set_client.

collation_connection — указывает сопоставление символов текущей, установленной, кодировки X.

Просмотреть текущие значения этих переменных можно следующим MySQL-запросом:

SHOW VARIABLES LIKE ‘character_set%’;
SHOW VARIABLES LIKE ‘collation%’;

Все эти действия желательно производить перед установкой скрипта, то есть еще перед тем, как он занесет данные в БД, чтобы избежать проблем с кодировкой в будущем.

Если Вы все равно наблюдаете «кракозябры», но уверены, что данные в БД хранятся в верной кодировке, то проверьте наличие директивы:

AddDefaultCharset X

в файле .htaccess и закомментируйте ее, если она там присутствует, а также укажите браузеру определять кодировку сайта автоматически.

В начале статьи я сказал, что мы заведомо уверены в том, что данные в БД хранятся в той же кодировке, что и таблицы, но а что, если это не так? Об этом в следующей статье. = )

Как избежать проблем с кодировками: 7 комментариев

  1. Ждем следующую статью, т.к. из этой ничего не понятно. 🙂 В смысле как победить то, что уже набедокурил.

  2. Очень полезная статья. Прописал одну строчку и все заработало. Спасибо Автору.

  3. Не нашел как написать автору блога об ошибке, надеюсь прочтет и удалит 🙂
    Короче при нажатии на «подписку RSS» открывается страница со сплошным текстом. У меня браузер: CHROME 8. Надеюсь на исправление бага.

  4. Скорее всего, что Хром не поддерживает этот тип RSS. Opera и FF открывают. На днях проверю, в чем дело. Спасибо. = )

  5. Спасибо за статью, очень помогла. Я решил проблему за «5 минут», над которой бился последнюю неделю.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *