php UTF-8 字符编码之战 json_encode()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/2790027/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UTF-8 character encoding battles json_encode()
提问by Dave Jarvis
Quest
寻求
I am looking to fetch rows that have accented characters. The encoding for the column (NAME) is latin1_swedish_ci.
我正在寻找具有重音字符的行。列 ( NAME)的编码是latin1_swedish_ci。
The Code
编码
The following query returns Abord a Plouffeusing phpMyAdmin:
以下查询Abord a 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
The following displays expected values (function is called db_fetch_all( $result )):
下面显示了预期值(函数被调用db_fetch_all( $result )):
  while( $row = mysql_fetch_assoc( $result ) ) {
    foreach( $row as $value ) {
      echo $value . " ";
      $value = utf8_encode( $value );
      echo $value . " ";
    }
    $r[] = $row;
  }
The displayed values: 5482 5482 Abord a Plouffe Abord ?¢ Plouffe
显示值: 5482 5482 Abord a Plouffe Abord ?¢ Plouffe
The array is then encoded using json_encode:
然后使用json_encode以下方法对数组进行编码:
$rows = db_fetch_all( $result );
echo json_encode( $rows );
Problem
问题
The web browser receives the following value:
Web 浏览器接收以下值:
{"ID":"5482","NAME":null}
Instead of:
代替:
{"ID":"5482","NAME":"Abord a Plouffe"}
(Or the encoded equivalent.)
(或编码的等价物。)
Question
题
The documentation states that json_encode()works on UTF-8. I can see the values being encoded from LATIN1 to UTF-8. After the call to json_encode(), however, the value becomes null.
该文档说明json_encode()适用于 UTF-8。我可以看到值从 LATIN1 编码为 UTF-8。json_encode()但是,在调用 之后,该值变为null。
How do I make json_encode()encode the UTF-8 values properly?
如何json_encode()正确编码 UTF-8 值?
One possible solution is to use the Zend Framework, but I'd rather not if it can be avoided.
一种可能的解决方案是使用Zend Framework,但如果可以避免,我宁愿不要。
回答by Kemo
// 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);
回答by bobince
foreach( $row as $value ) {
  $value = utf8_encode( $value );
You're not actually writing your encoded value back into the $rowarray there, you're only changing the local variable $value. If you want to write back when you change the variable, you would need to treat it as a reference:
您实际上并没有将编码值写回$row那里的数组,您只是更改了局部变量$value。如果要在更改变量时回写,则需要将其视为引用:
foreach( $row as &$value ) {
Personally I would try to avoid references where possible, and for this case instead use array_mapas posted by Kemo.
我个人会尽量避免引用,在这种情况下,请使用array_mapKemo 发布的内容。
Or mysql_set_charsetto UTF-8 to get the return values in UTF-8 regardless of the actual table collations, as a first step towards migrating the app to UTF-8.
或者mysql_set_charset到 UTF-8 以获取 UTF-8 中的返回值,而不管实际的表排序规则如何,作为将应用程序迁移到 UTF-8 的第一步。
回答by jailsonjan
My solution is insert this line mysql_query('SET CHARACTER SET utf8');, before the SELECT.
This method is good.
我的解决方案是mysql_query('SET CHARACTER SET utf8');在SELECT. 这个方法很好。
回答by Robert Imhoff
It seems that rather than putting it in a query, one should put:
似乎与其将其放入查询中,不如将其放入:
mysql_set_charset('utf8');
after the mysql connect statement.
在 mysql 连接语句之后。
回答by alditis
In your connect: mysql_set_charset('utf8', $link);
在您的连接中: mysql_set_charset('utf8', $link);
Example:
例子:
<?php
$link = mysql_connect('localhost', 'your_user', 'your_password');
mysql_set_charset('utf8', $link);
$db_selected = mysql_select_db('your_db', $link);
...
Hope that helps somewhat.
希望有所帮助。
回答by Wil
Try iconv_r($row,"LATIN1","UTF-8//TRANSLIT");(function below) before you json_encode()your result.
iconv_r($row,"LATIN1","UTF-8//TRANSLIT");在json_encode()您获得结果之前尝试(下面的功能)。
I have UTF-8 as the table encoding and as the result set encoding, but sometimes folks still manage to submit non-UTF-8 characters via forms and it's troublesome to track down every single input source so I have also wrapped json_encode()to make it safer.  In particular I've had it NULL strings on me containing the degree symbol and "smart quotes" which folks in the UK seem so fond of.
我有 UTF-8 作为表编码和结果集编码,但有时人们仍然设法通过表单提交非 UTF-8 字符,而且追踪每个输入源很麻烦,所以我也进行了包装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);
         }
      }
   }
}

