通常Mysql表設計時,都是用UTF8字符集的。把帶有emoji的暱稱字段往裏面insert一下就沒了,整個字段變成了空字符串。這是怎麼回事呢? 原來是由於Mysql的utf8字符集是3字節的,而emoji是4字節,這樣整個暱稱就沒法存儲了。這要怎麼辦呢 一、使用utf8mb4字符集
一、mysql的版本必須爲v5.5.3或更高 二、把數據庫的編碼改爲utf8mb4 -- UTF-8 Unicode 三、而後須要存儲emoji表情的字段選擇utf8mb4_general_ci 四、數據庫鏈接也須要改成utf8mb4 這種方式可能帶來的問題: 存儲:在數據表中,對於變長的字段(如VARCHAR2,TEXT),utf8mb4最大可存儲的字符可能少於utf8系列的collation;
在索引中,對於文本類型的字段,utf8mb4可索引的字符少於utf8系列的collations。如InnoDB的索引最多使用767字節。
若是使用utf8mb4,每個字符都會預留4字節作索引,而utf8則預留3字節。故此前者是191個字符,後者是255個字符。 性能:因爲以上緣由,加上字符集大,utf8mb4的性能可能比utf8系列的collations低,
能夠參考stackoverfolow上的一個測試結果:http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci,
差別不是特別大。 運維:若是一個大的環境內,若是其餘的數據庫都是utf8模式,把其中某個庫設置爲utf8mb4模式,在後續交接運維可能會形成問題,遺留下坑。 上下游:數據庫支持unicode的emoji存儲,上下游不必定支持。好比mysql客戶端驅動(低版本的jdbc就不行)可能不支持utf8mb4,或者DDL的中間件不支持utf8mb4。
web端處理utf8mb4字符展現,這些都有可能影響emoji的存儲活着展現。 二、使用base64編碼
這種方法是能夠,可是舊數據若是沒有通過encode操做,取數據的時候若是統一進行decode的話,舊數據會丟失的。
三、過濾emoji表情
支持emoji表情是個麻煩的東西,有時即便能存儲,也不必定能完美顯示。可能會出現因emoji圖片不夠全而出現沒法顯示的狀況。而且有些客戶端可能還須要使用第三方類庫,須要大量的emoji圖片等。
所以,若是emoji不是非要不可,咱們能夠把帶有emoji內容的數據過濾掉,達到不影響其餘數據的存儲。
// 過濾掉emoji表情 function filterEmoji($str) { $str = preg_replace_callback('/./u',function (array $match) { return strlen($match[0]) >= 4 ? '' : $match[0]; },$str); return $str; }
四、文本轉義emoji表情
/** 把用戶輸入的文本轉義(主要針對特殊符號和emoji表情) */ public function userTextEncode($str){ if (!is_string($str)) return $str; if (!$str || $str=='undefined') return ''; $text = json_encode($str); //暴露出unicode $text = preg_replace_callback("/(\\\u[ed][0-9a-f]{3})/i",function($str){ return addslashes($str[0]); },$text); //將emoji的unicode留下,其餘不動,這裏的正則比原答案增長了d,由於我發現我不少emoji其實是\ud開頭的,反而暫時沒發現有\ue開頭。 return json_decode($text); } /** 解碼上面的轉義 */ public function userTextDecode($str){ $text = json_encode($str); //暴露出unicode $text = preg_replace_callback('/\\\\\\\\/i',function($str){ return '\\'; },$text); //將兩條斜槓變成一條,其餘不動 return json_decode($text); }
*推薦使用文本轉義emoji表情