После обновления PHP на нашем сервере разработки с 5.2 до 5.3 мы сталкиваемся с проблемой, когда данные, запрошенные из нашей базы данных и отображаемые на веб-странице, показывают неправильную кодировку при попытке отобразить русские символы.
В PHP 5.3 клиентская библиотека по умолчанию для взаимодействия с базами данных MySQL изменилась с libmysql на mysqlnd , что, по-видимому, является причиной проблемы, с которой мы сталкиваемся.
Мы подключаемся к базе данных со следующим кодом:
$conn = mysql_pconnect('database.hostname', 'database_user', 'database_password'); $mysql_select_db('database', $conn);
Данные, хранящиеся в нашей базе данных, кодируются кодировкой UTF-8. Подключение к базе данных через клиент командной строки и выполняемые запросы подтверждает, что данные не повреждены и правильно закодированы. Однако, когда мы запрашиваем базу данных в PHP и пытаемся отобразить одни и те же данные, она становится искаженной. В этом конкретном случае мы пытаемся отображать русские символы, а результат – неанглийские, нерусские символы:
Заголовки ответов, которые мы получаем, подтверждают, что тип содержимого – UTF-8:
Мы тестировали строки перед отображением с mb_detect_encoding в строгом режиме, а также mb_check_encoding, и им сказали, что строка была строкой UTF-8 перед ее отображением. Мы также использовали mysql_client_encoding для проверки клиентской кодировки, а также указывает, что набор символов – UTF-8.
При проведении исследований мы обнаружили некоторые предложения по решению этой проблемы:
header("Content-type: text/html; charset=utf-8"); mysql_set_charset('utf8'); mysql_query("SET SESSION character_set_results = 'UTF8'"); mysql_query('SET NAMES UTF8', $conn);
Мы даже пытались использовать utf8_encode :
utf8_encode($string);
Однако ни одно из этих решений не работало.
Исходя из опций, мы обновили MySQL в нашей системе разработки до версии 5.1.55. После этого обновления все отображается правильно, когда мы подключались к нашей базе данных разработки. Конечно, он продолжает отображаться некорректно, когда мы подключаемся к нашей базе данных.
В идеале мы хотели бы решить эту проблему без обновления MySQL на наших производственных серверах, если мы не сможем проверить точную причину, по которой это не работает, и почему обновление исправит его. Как решить эту проблему без обновления MySQL? В качестве альтернативы, почему обновление MySQL исправляет проблему?
Если вы убедитесь, что обе таблицы и выходная кодировка являются UTF-8, почти единственное, что осталось, это кодирование соединения.
Причиной изменения поведения при обновлении серверов может быть изменение кодировки соединения по умолчанию:
[mysql] default-character-set=utf8
Тем не менее, я не вижу изменений в кодировке по умолчанию между версиями, поэтому, если это были совершенно новые установки, я не вижу этого.
В любом случае, что произойдет, если вы запустите это из вашего PHP-запроса и выведете результаты. Любые отличия от вывода командной строки?
SHOW VARIABLES LIKE 'character_set%'; SHOW VARIABLES LIKE 'collation%';
Я вижу, вы пробовали это, но синтаксис, который я использую: mysql_query ("SET NAMES utf8"). Ваш синтаксис может быть правильным, я никогда раньше этого не видел.
Пример:
// connect to database stuff $Connection = mysql_connect($server, $username, $password) or die ("Error connecting to server"); // connect to database stuff $db = mysql_select_db($database, $Connection) or die ("Error selecting database"); mysql_query("SET NAMES utf8");
У меня была аналогичная проблема после обновления PHP с 5.2.3 до 5.3.5 (5.3.5-Win32-VC6-x86), MySQL 5.0.41 (не обновлено). Я думаю, что причина – небольшая разница между версиями PHP.
PHP 5.2.3 по умолчанию (без SET NAMES):
character_set_client = latin1
character_set_connection = latin1
character_set_database = utf8
character_set_filesystem = двоичный
character_set_results = latin1
character_set_server = latin2
character_set_system = utf8
collation_connection = latin1_swedish_ci
collation_database = utf8_polish_ci
collation_server = latin2_general_ci
PHP 5.3.5 по умолчанию (без SET NAMES):
character_set_client = latin2
character_set_connection = latin2
character_set_database = utf8
character_set_filesystem = двоичный
character_set_results = latin2
character_set_server = latin2
character_set_system = utf8
collation_connection = latin2_general_ci
collation_database = utf8_polish_ci
collation_server = latin2_general_ci
Я добавил данные в базу данных в PHP 5.2.3 по умолчанию (без SET NAMES), поэтому теперь, чтобы правильно отобразить его, я должен прочитать его, используя:
$pdo -> query("SET NAMES 'latin1'");
Возможно, что-то подобное является причиной вашей проблемы.