PHP输出编码与MySQL数据库中的UTF-8字符串有关

时间:2015-06-23 00:47:09

标签: php mysql encoding utf-8 character-encoding

我知道这个问题在这里一直以某种形式出现,但我对如何解决它有点不知所措。我有一个PHP网站运行MySQL,它显示一些扩展字符作为乱码。据我所知,它全部编码为UTF-8,从内容导入到在屏幕上显示它的每一步。不过,它显示出奇怪的编码问题。这是第一个测试示例(NaturalPhënåm¥na,这是故意的),mb_detect_encoding标识为UTF-8,我只能使用utf8_decode正确显示:

no utf8_decode: Natural Phënåm¥na
utf8_decode: Natural Phënåm¥na

第二个例子,它甚至从来没有正确地使用utf8_decodes(应该是一个ümlaut和“typographer's quotes”(扩展字符是故意添加的,作为测试:

no utf8_decode: This pürson from “Vancouver, Canadaâ€
utf8_decode: This pürson from �??Vancouver, Canada�?�

我最初的想法是它是双重编码的,但我不认为这是正在发生的事情。当我在命令行上进行查询时,一切都在MySQL中正确显示。

以下是我调查过的所有事情的简要说明:

  • 导入的内容经验证为UTF-8,使用UTF-8连接导入MySQL
  • MySQL数据库,表,列是UTF-8,utf_unicode _ *
  • 在Amazon RDS上设置为utf8的MySQL中的character_set_client等变量
  • PHP PDO连接为UTF-8,NAME设置为UTF-8
  • PHP标头字符集和HTML元字符集都是UTF-8
  • mb_detect_encoding为两个字符串
  • 返回UTF-8

经过几个小时的故障排除后,我有点不知所措。一时兴起,我甚至尝试将HTML标头/元和PHP标头设置为ISO-8559-1,但这也没有做到。

我上次花了一段时间与Amazon RDS进行斗争,以获得正确的变量设置,但除此之外我没有想法。

mysql> show variables like '%character%';
+--------------------------+-------------------------------------------+
| Variable_name            | Value                                     |
+--------------------------+-------------------------------------------+
| character_set_client     | utf8                                      |
| character_set_connection | utf8                                      |
| character_set_database   | utf8                                      |
| character_set_filesystem | utf8                                      |
| character_set_results    | utf8                                      |
| character_set_server     | utf8                                      |
| character_set_system     | utf8                                      |
| character_sets_dir       | /rdsdbbin/mysql-5.5.40.R1/share/charsets/ |
+--------------------------+-------------------------------------------+

所以我想知道,我有缺失的步骤吗?有什么明显的吗?提前谢谢。

更新

这是我的PHP输出脚本,有关我提到的“输出”的进一步说明:

<?php header("Content-type: text/html; charset=utf-8"); ?>
<html>
<header>
    <meta charset="utf-8" />
    <title>My test</title>
</header>
    <body>
<?php


    try {
        $dbh = new PDO("mysql:host=localhost;dbname=database", 
        "user", "password", array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
    }
    catch(PDOException $e) {
        echo $e->getMessage();
    }

    $sth = $dbh->prepare("my select statement");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);


foreach ($rows as $row) {
    echo mb_detect_encoding($row['name']);
    echo "<br>no utf8 decode: ". $row['name'] . "<br>\n";
    echo "single utf8 decode: ". utf8_decode($row['name']) . "<br>\n";
    echo "no utf8 decode: ". $row['description'] . "<br>\n";
    echo "single utf8 decode: ". (utf8_decode($row['description'])) . "<br>\n";
}

?>
</body>
</html>

更新#2 我还尝试直接从PHP回显和直接静态HTML将这些相同的字符输出到浏览器中,并且字符显示完美。

echo "“test ü ö”<br>"; ?>
<p>“test ü ö”</p>

3 个答案:

答案 0 :(得分:1)

您不应更改所有character_set%字段,只需更改受SET NAMES utf8;影响的三个字段。

请勿使用utf8_encode或解码。

存储时你可能搞砸了。

这似乎可以恢复角色,但这不是一个可行的解决办法:

CONVERT(CAST(CONVERT('pürson from “Vancouver, Canadaâ€' USING latin1)
             AS BINARY)
        USING utf8)
--> 'pürson from “Vancouver, Canada - spec',

为了弄清楚做了什么,请提供

SELECT col, HEX(col) FROM tbl WHERE ...

对于某些无法正常渲染的单元格。

答案 1 :(得分:0)

你提到它在所有数据流中都是utf-8,除非它在屏幕上呈现。我假设是在浏览器上,而不是控制台。如果是这样,请检查html是否在<meta charset="utf-8">标记内包含<head>。就像在html5样板https://github.com/h5bp/html5-boilerplate/blob/master/dist/index.html

中一样

答案 2 :(得分:0)

所以看起来在某种程度上它在MySQL级别上是在其中一些字段中对UTF-8字符进行双重编码。我终于能够通过这篇精彩的博客文章Getting out of MySQL Character Set Hell来确定它。不是100%清楚,如果它是&#34;双重编码&#34;当它从Python发送时,或者当它发送到PHP API时,但它的答案是90%,就在那里。