簡體   English   中英

來自 MySQL 數據庫的 UTF-8 字符串的 PHP 輸出編碼問題

[英]PHP output encoding issues with UTF-8 strings from MySQL databases

我知道這個問題在這里一直以一種或另一種形式出現,但我對如何解決它有點不知所措。 我有一個運行 MySQL 的 PHP 網站,將一些擴展字符顯示為亂碼。 據我所知,從內容導入到在屏幕上顯示的每一步都被編碼為 UTF-8。 盡管如此,它仍然顯示出奇怪的編碼問題。 這是第一個測試示例(Natural Phë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 和“排版師的引號”(故意添加的擴展字符,作為測試:

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 上,MySQL 中的 character_set_client 等變量設置為 utf8
  • 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 echo 和直接的靜態 HTML 將這些相同的字符輸出到瀏覽器中,並且字符顯示得非常好。

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

您不應更改所有character_set%字段,僅更改受SET NAMES utf8;影響的三個字段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 ...

對於某些未正確渲染的單元格。

您提到在所有數據流中都是 utf-8 格式,除非它在屏幕上呈現。 我假設在瀏覽器上,而不是控制台上。 如果是這樣,請檢查 html 的<head>標簽內是否有<meta charset="utf-8"> 就像在 html5 樣板中一樣https://github.com/h5bp/html5-boilerplate/blob/master/dist/index.html

所以它看起來在 MySQL 級別上以某種方式在其中一些字段中對 UTF-8 字符進行了雙重編碼。 我終於能夠通過這篇很棒的博客文章走出 MySQL 字符集地獄來確定它。 不是 100% 清楚當它從 Python 發送時是否被“雙重編碼”,或者當它擊中 PHP API 時,但它是 90% 的答案,就在那里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM