поиск
Я ищу, чтобы получить строки с акцентированными символами. Кодировка для столбца ( NAME
) – latin1_swedish_ci
.
Код
Следующий запрос возвращает Abord â Plouffe
с помощью phpMyAdmin:
SELECT C.NAME FROM CITY C WHERE C.REGION_ID=10 AND C.NAME_LOWERCASE LIKE '%abor%' ORDER BY C.NAME LIMIT 30
Ниже отображаются ожидаемые значения (функция называется db_fetch_all( $result )
):
while( $row = mysql_fetch_assoc( $result ) ) { foreach( $row as $value ) { echo $value . " "; $value = utf8_encode( $value ); echo $value . " "; } $r[] = $row; }
Отображаемые значения: 5482 5482 Abord â Plouffe Abord â Plouffe
Затем массив кодируется с помощью json_encode
:
$rows = db_fetch_all( $result ); echo json_encode( $rows );
проблема
Веб-браузер получает следующее значение:
{"ID":"5482","NAME":null}
Вместо:
{"ID":"5482","NAME":"Abord â Plouffe"}
(Или закодированный эквивалент.)
Вопрос
В документации указано, что json_encode()
работает в UTF-8. Я могу видеть, что значения кодируются от LATIN1 до UTF-8. Однако после вызова json_encode()
значение становится равным null
.
Как заставить json_encode()
правильно кодировать значения UTF-8?
Одно из возможных решений – использовать Zend Framework , но я бы предпочел, если этого можно избежать.
// Create an empty array for the encoded resultset $rows = array(); // Loop over the db resultset and put encoded values into $rows while($row = mysql_fetch_assoc($result)) { $rows[] = array_map('utf8_encode', $row); } // Output $rows echo json_encode($rows);
foreach( $row as $value ) { $value = utf8_encode( $value );
Вы на самом деле не записываете свое закодированное значение в массив $row
, вы меняете только локальную переменную $value
. Если вы хотите записать обратно при изменении переменной, вам нужно будет рассматривать ее как ссылку:
foreach( $row as &$value ) {
Лично я старался избегать ссылок там, где это возможно, и для этого случая вместо этого используйте array_map
как опубликовал Kemo.
Или mysql_set_charset
для UTF-8, чтобы получить возвращаемые значения в UTF-8, независимо от фактических сопоставлений таблиц, в качестве первого шага к переносу приложения в UTF-8.
Мое решение вставляет эту строку mysql_query('SET CHARACTER SET utf8');
, перед SELECT
. Этот метод хорош.
Кажется, что вместо того, чтобы помещать его в запрос, нужно поставить:
mysql_set_charset('utf8');
после инструкции mysql connect.
В вашем подключении: mysql_set_charset('utf8', $link);
Пример:
<?php $link = mysql_connect('localhost', 'your_user', 'your_password'); mysql_set_charset('utf8', $link); $db_selected = mysql_select_db('your_db', $link); ...
Надеюсь, что это помогает.
Попробуйте iconv_r($row,"LATIN1","UTF-8//TRANSLIT");
(функция ниже) перед вами json_encode()
ваш результат.
У меня есть UTF-8 в качестве кодировки таблицы и в качестве кодировки с результирующим набором, но иногда люди все еще могут отправлять символы без UTF-8 через формы, и json_encode()
каждый отдельный источник, поэтому я также завернул json_encode()
в сделайте его более безопасным. В частности, у меня на нем были NULL строки, содержащие символ степени и «умные кавычки», которые так любят люди в Великобритании.
function safe_json_encode($mixed,$missing="TRANSLIT"){ $out=json_encode($mixed); if ($err= json_last_error()){ iconv_r("UTF-8","UTF-8//$missing",$mixed); $out=json_encode($mixed); } return $out; } function iconv_r($charset_i, $charset_o, &$mixed) { if (is_string($mixed)) { $mixed = iconv($charset_i, $charset_o, $mixed); } else { if (is_object($mixed)){ $mixed = (array) $mixed; } if (is_array($mixed)){ foreach ($mixed as $key => &$value) { iconv_r($charset_i, $charset_o, $value); } } } }