2015-05-14 27 views
2

我正在對正在使用UTF8編碼,具有包含特殊字符的很多的用戶名,如「Ғђ▫索尼」流明MySQL查詢不處理UTF8值如預期

當查詢用戶表的數據庫,流明響應不正確的數據。我試着用mysqliPDO查詢同一張表,我收到了預期的結果。我成立了一個樣本路徑進行測試:

$app->get("charset", function() { 
    $mysqli = new mysqli("localhost", "user", "password", "database"); 
    $res = $mysqli->query("select name from users where id = 1"); 

    $dbh = new PDO('mysql:host=localhost;dbname=database', "user", "password"); 
    $stmt = $dbh->query("select name from users where id = 1"); 

    $lumen = DB::select("select name from users where id = 1"); 

    return response()->json([ 
     "mysqli" => $res->fetch_assoc(), 
     "pdo" => $stmt->fetchAll(PDO::FETCH_ASSOC), 
     "framework" => $lumen 
    ]); 
}); 

當訪問路線,我得到如下回應:

{ 
    "mysqli": { 
    "name": "Ғђ ▫ Sony" 
    }, 
    "pdo": [ 
    { 
     "name": "Ғђ ▫ Sony" 
    } 
    ], 
    "framework": [ 
    { 
     "name": "Ò’Ñ’ â–« Sony" 
    } 
    ] 
} 

這裏是萬一上面的文字顯示不正確響應的屏幕截圖:broken UTF8 response

據我所知,流明的MySQL的配置默認爲UTF8,是不變的 - 我發現vendor/laravel/lumen-framework/config/database如下:

'mysql' => [ 
    'driver' => 'mysql', 
    'host'  => env('DB_HOST', 'localhost'), 
    'database' => env('DB_DATABASE', 'forge'), 
    'username' => env('DB_USERNAME', 'forge'), 
    'password' => env('DB_PASSWORD', ''), 
    'charset' => 'utf8', 
    'collation' => 'utf8_unicode_ci', 
    'prefix' => env('DB_PREFIX', ''), 
    'timezone' => env('DB_TIMEZONE','+00:00'), 
    'strict' => false, 
], 

我不知道是什麼原因造成的。我還有什麼可以嘗試追查這種差異?

+0

數據庫中的數據是否正確保存?你可以看到正確的特殊字符,比如使用MYSQL Workbench或者類似的工具嗎? –

+0

當我通過My​​SQL Workbench查詢它時,它返回「Ò''''-«Sony」作爲名稱。我嘗試添加'SET NAMES'utf8'',但它似乎沒有效果。 –

+0

編碼問題總是很有趣,我有一些自己......如果你認爲數據庫設置是好的,你可能要仔細檢查,如果其餘的工作....在打印出你的結果之前,這會使更改..... header('Content-Type:text/html; charset = utf-8'); //(在你開始打印我們的東西之前將其放置) – lauw

回答

1

這個答案是基於我上面的評論。

MySQL連接字符集定義了什麼編碼用於MySQL客戶端(PHP)和服務器之間的通信。在實際的MySQL表中使用什麼編碼作爲內部編碼並不重要。 MySQL服務器將自動轉換表編碼和連接編碼之間的數據。所以連接編碼基本上定義了您希望從MySQL獲取數據的格式,以及您將數據插入MySQL的格式。

您確定數據在數據庫的utf8中正確編碼嗎?

看起來像你只是使用UTF8作爲流明數據庫連接(如果這是默認設置),但不使用UTF8和你的mysqli或PDO連接示例。如果使用$mysqli->set_charset("utf8");和使用new PDO('mysql:host=localhost;dbname=database;charset=utf8', "user", "password");的PDO字符集來設置mysqli字符集,你會得到相同的結果嗎?

根據您的代碼和輸出示例,您似乎從流明數據庫連接正確獲取UTF8數據,但輸出不顯示爲UTF8。

這也解釋了爲什麼mysqli和PDO輸出顯示正確,因爲它們沒有以UTF8返回數據(因爲您沒有將它們的連接字符集設置爲UTF8),但默認情況下,它們似乎與任何編碼匹配,重新顯示輸出(顯然是「latin1」或兼容)。

如果您正在Web瀏覽器中查看輸出,請確保正確定義了輸出頁面charset(例如,使用標題)。

編輯:

順便說一句不應該不管什麼連接編碼中,只要連接編碼匹配是通過連接發送的數據的編碼是插入數據的其他系統中使用。

將連接編碼設置爲latin1意味着當您執行SELECT操作時,您將獲得字符串數據作爲latin1。所以看起來你的輸出被處理爲latin1而不是UTF-8。如果您的輸出環境(例如Web瀏覽器)支持它,則修正腳本輸出以正確顯示「爲UTF-8」可能會更好。因爲否則,如果您需要處理無法在latin1中顯示的字符,您將遇到問題。雖然如果你輸出到CLI終端/控制檯,當然你應該使用相同的編碼作爲默認終端編碼(可以是UTF-8或其他)。我更喜歡將我的Linux終端配置爲UTF-8。

+0

所有這些令人困惑的事情是,我的頁面的輸出字符集是UTF-8 - 我對此有1000%的把握,因爲我已經多次檢查了它十次。無論哪種方式,你的答案幫助我得到它的工作,所以這對我來說已經足夠了。再次感謝! –