說明
在使用 PHP 的時候,可能會遇到編解碼的錯誤。這里面的編解碼包括 BASE64、json_encode、json_decode 等。
下面是使用 YII2 框架,一個請求在返回數據的數據時候,出現的錯誤:
Malformed UTF-8 characters, possibly incorrectly encoded.
問題和解決方案
出現上面的問題,可能有下面幾種情況:
字符集不統一
編解碼前后使用的字符集不一致,導致編碼成一種字符集,解碼的時候是另一種字符集。要檢查編解碼前后的字符集是否一致。
可以使用下面的一些函數進行檢查。
# 設置內部字符編碼為 UTF-8
mb_internal_encoding("UTF-8");
# 顯示當前的內部字符編碼
echo mb_internal_encoding();
# 檢測 HTTP 輸入字符編碼
mb_http_input()
# 設置/獲取 字符編碼的檢測順序
mb_detect_order()
# 設置/獲取 HTTP 輸出字符編碼
mb_http_output()
# 設置/獲取多字節正則表達式的字符編碼
mb_regex_encoding()
全局設置指定的字符集
方法1:代碼中設置成 UTF-8 字符集:
mb_internal_encoding("UTF-8")
方法2:在 php.ini 中設置
mbstring.internal_encoding = UTF-8
字符集轉換
將指定字符串從 encoding1 字符集。
mb_convert_encoding($str, $encoding1, $encoding2);
參數說明encoding1:目標編碼,如utf-8,gbk,大小寫均可;
$encoding2:原編碼,如utf-8,gbk,大小寫均可。
案例一
$str='你好,世界';
// 編碼轉換為utf-8
echo mb_convert_encoding($str, "UTF-8");
案例二
$str='你好,世界';
// 已知原編碼為GBK,轉換為utf-8
echo mb_convert_encoding($str, "UTF-8", "GBK");
案例三
$str='你好,世界';
// 把 GBK,GB2312,BIG5 這幾種編碼轉成 UTF-8 編碼。
$content = mb_convert_encoding($str, 'UTF-8', 'GBK,GB2312,BIG5');
案例四
$str='你好,世界';
// 未知原編碼,通過auto自動檢測后,轉換編碼為utf-8
echo mb_convert_encoding($str, "UTF-8", "auto");
不可編碼的數據
在使用 json 進行編碼的時候,編碼的數據可能經過 base64 進行解碼,但是原數據可能不是 base64 編碼的,因此會導致 base64 解碼錯誤,然后再使用 json 進行 json_encode 等編碼時,出現上面的錯誤。
該問題需要檢查進入 json_encode 的數據,是否是正常數據,如果操作的數據不是正常字符數據,json_encode 可能會返回空,也可能會返回 true、false 之類的數據,也可能報錯。
在 YII2 中,如果返回的是 JSON 格式的數據,框架在執行 Respnose 方法的時候,會調用
BaseJson.php 中的 encode 方法:
BaseJson::encode($str);
如果 $str 數據不是正常數據,此處也會報上面的錯誤。
所以要檢查好 json_encode 的數據是否是正常數據。