著作權聲明:此文章轉載自跡憶( http://www.onmpw.com/tm/xwzj/prolan_122.html?
hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io )
如需轉載請聯絡聽雲College團隊成員小尹 郵箱:yinhy#tingyun.com
在PHP項目中會經常遇到中文亂碼,這是一個比較惱人的問題。不過,當需要將內容輸出到網頁上的時候,我們遵照以下兩個原則一般情況下是不會出現中文亂碼的。
第一就是在html頭部添加
第二點就是保證檔案的編碼和meta設定的編碼一致。也就是說,如果我們第一條設定的charset為UTF-8,那我們的檔案編碼也要設定成UTF-8。二者保持一致即可。
當然上面是針對於網頁的情況,但是現在隨著Ajax在web應用中佔得比重越來越大,json格式的資料在資料轉送中應用也越來越廣。因此在PHP中使用json_encode對資料進行json轉換的時候也會遇到中文亂碼或者是對中文進行編碼的問題。
舉個例子來說
$data = array('id'=>1,'name'=>'跡憶部落格','parId'=>0);echo json_encode($data);
上面代碼的輸出結果為
{"id":1,"name":"\u8ff9\u5fc6\u535a\u5ba2","parId":0}
我們看,函數對中文’跡憶部落格’進行了16進位轉碼。這不能說是錯誤,因為16進位表示的就是正確的中文,我們拿到這個結果以後,在前端通過js同樣也可以得到我們想要的結果。但是,這樣使用起來還是比較麻煩的。當然情況也會根據PHP的版本的不同而有所變化。
對於PHP的一些版本其結果會是如下的情況
{"id":1,"name":null,"parId":0}
中文無法被正確的解析出來。
沒有辦法,中文問題就是這麼麻煩。誰讓電腦不是中國人發明的呢。當然這些是有解決方案的,下面我們就來瞭解兩個解決的辦法。
一、通過json_encode第二個參數來解決
針對上面問題,在PHP>=5.4.0 的版本已經可以直接通過json_encode函數本身來解決。那就是第二個參數加上JSON_UNESCAPED_UNICODE。
$data = array('id'=>1,'name'=>'跡憶部落格','parId'=>0);echo json_encode($data, JSON_UNESCAPED_UNICODE);
現在就能得到正確的結果
{"id":1,"name":"跡憶部落格","parId":0}
結果是能正確的得到了。但是,對於PHP的版本總不能讓大家都換成5.4及以上的版本吧。那對於5.4以下的版本應該怎麼處理呢?
二、通過url編碼解決中文問題
我們知道,在PHP中有兩個函數 urlencode 和 urldecode。我們可以通過urlencode函數將中文進行url編碼,這樣在字串中就不會再有中文,也就不會遇到中文編碼的問題。
$str = “跡憶部落格”;echo urlencode($str);
對跡憶部落格進行url編碼,其結果如下
%E8%BF%B9%E5%BF%86%E5%8D%9A%E5%AE%A2
所以說,我們將上面數組的name的值用urlencode編碼以後,再進行json格式轉化,那中文編碼的問題就不存在了。
$data = array('id'=>1,'name'=>urlencode('跡憶部落格'),'parId'=>0);$res = json_encode($data);echo $res;
現在我們得到的結果就是name編碼以後的json字串
{"id":1,"name":"%E8%BF%B9%E5%BF%86%E5%8D%9A%E5%AE%A2","parId":0}
最後再通過urldecode對url編碼的字串進行解碼。當然urldecode解碼不用我們再去找對應的那一段編碼的字串進行解碼。我們可以直接對整個字串進行url解碼。urldecode會自動去檢測相應的url編碼的字串對其進行解碼。
$data = array('id'=>1,'name'=>urlencode('跡憶部落格'),'parId'=>0);$res =urldecode(json_encode($data));echo $res;
這樣其結果就是正確的了
{"id":1,"name":"跡憶部落格","parId":0}
這種方法是沒有版本限制的,但是效率的話肯定會相對於第一種方法要慢一些。
針對第二個方法——通過url編碼解決中文問題——的封裝函數
現在問題來了,對於第二個方法,我們總不能在數組的每一個中文前面都加上urlencode函數吧!這也是不現實的。那我們可以通過自己封裝json_encode函數來處理這樣的問題。
代碼如下
/** * 作者:跡憶 * 個人部落格:跡憶部落格 * 部落格url:www.onmpw.com*/function onmpw_json_encode($data){ if(is_object($data)) return false; if(is_array($data)){ $data = deal_array($data); } return urldecode(json_encode($data));}function deal_array($data){ if (is_array($data)) { foreach ($data as $key => $val) { if (is_array($val)) { //如果是多維陣列,通過遞迴來處理多維陣列 $data[$key] = deal_array($val); } else { //對值進行url編碼 $data[$key] = urlencode($val); } } } elseif (is_string($data)) { $data = urlencode($data); } return $data;}
下面我們來看一個使用樣本
$data = array( array('id'=>1,'name'=>'跡憶部落格','parId'=>0), array('id'=>2,'name'=>'學無止境','parId'=>1), array('id'=>3,'name'=>'趣味雜談','parId'=>1), array('id'=>4,'name'=>'程式設計語言','parId'=>2), array('id'=>5,'name'=>'網路','parId'=>2), array('id'=>6,'name'=>'演算法','parId'=>2), array('id'=>7,'name'=>'作業系統','parId'=>2), array('id'=>8,'name'=>'資料庫','parId'=>2), array('id'=>9,'name'=>'WEB前端','parId'=>2), array('id'=>10,'name'=>'讀書','parId'=>3), array('id'=>11,'name'=>'觀點與感想','parId'=>3) );$data = onmpw_json_encode($data);echo $data;
現在我們得到了我們想要的結果
[{"id":"1","name":"跡憶部落格","parId":"0"},{"id":"2","name":"學無止境","parId":"1"},{"id":"3","name":"趣味雜談","parId":"1"},{"id":"4","name":"程式設計語言","parId":"2"},{"id":"5","name":"網路","parId":"2"},{"id":"6","name":"演算法","parId":"2"},{"id":"7","name":"作業系統","parId":"2"},{"id":"8","name":"資料庫","parId":"2"},{"id":"9","name":"WEB前端","parId":"2"}, {"id":"10","name":"讀書","parId":"3"},{"id":"11","name":"觀點與感想","parId":"3"}]
總結
中文編碼的問題很常見,我們大家要在實際情況中多總結。在以後的開發中再遇到類似的問題就可以很容易的解決了。
對於上面自訂的json_encode函數,我會把它封裝到一個公用類中。原始碼都在github上,我會持續將一些常用函數封裝到這個公用類中,歡迎大家點擊下載。希望這些對大家有所協助。
想閱讀更多技術文章,請訪問聽雲技術部落格,訪問聽雲官方網站感受更多應用效能最佳化魔力。