php数据库插入表情转换,如何转义emoji表情,让它可以存入utf8的数据库?
unicode emoji是4個字節(jié)的,存不進MySQL里,找到一個轉(zhuǎn)義的庫http://code.iamcal.com/php/emoji/,但是轉(zhuǎn)為Unicode之后,還是4個字節(jié),一樣存不進,應該說根本沒轉(zhuǎn)。轉(zhuǎn)為其他格式的emoji又怕以后新增了表情不好做,你們在不改數(shù)據(jù)庫編碼的前提下,是怎么弄的?
方法1:base_encode64
這種方法是可以,但是舊數(shù)據(jù)沒有經(jīng)過encode操作,取數(shù)據(jù)的時候如果統(tǒng)一進行decode的話,舊數(shù)據(jù)會丟失的。
方法2:urlencode
這個似乎可以,對沒有經(jīng)過encode的數(shù)據(jù)進行decode也不會有影響,而且多次decode似乎也不會有影響。你們說這個方法有缺陷嗎?
=======================
一個發(fā)現(xiàn),微信獲取用戶基本信息的時候,笑哭那個表情print_r出的是\ud83d\ude02,而我存儲的時候,報錯說這個 \xF0\x9F\x98\x82 值不能存儲,請問這是怎么回事,自動轉(zhuǎn)碼了,轉(zhuǎn)成的這是什么?是微信轉(zhuǎn)碼過了嗎?
=======================
方法3:最后采用了下面采納的那個方法,因為我覺得它有下面幾個優(yōu)點:
1、那個方法只轉(zhuǎn)換表情,不會轉(zhuǎn)換中文,所以數(shù)據(jù)還是直接可讀的
數(shù)據(jù)庫中存儲起來是這樣的,
后面的\ud83d\udca5可以隨意復制粘貼,而顯示出來是這樣的,
2、不會把表情轉(zhuǎn)換為其它標準,只有一個簡單的,固定的轉(zhuǎn)換算法,也就是說不需要一個表情庫來對照著轉(zhuǎn)換,所以以后其它人要使用這個數(shù)據(jù)的時候,也很容易知道每個表情是對應的哪個。就算蘋果大爺又增加了表情,也不需要做什么額外的修改。
3、可以無限decode輸出的都是正確的內(nèi)容。因為有的時候可能需要在一次請求中的兩個地方做decode,其它decode多次會把正確的數(shù)據(jù)改成其它數(shù)據(jù),這個不會。
缺點:
1、看了下面的代碼就知道,這個是強制修改字符編碼中,指定區(qū)間內(nèi)的編碼,也就說有可能誤殺,也有可能有超出這個區(qū)間的emoji沒殺到。不過僅僅是在字符前加反斜杠,即使誤殺了,發(fā)現(xiàn)之后也很容易改回來。
數(shù)據(jù)庫中發(fā)現(xiàn)有這樣的
,是漏殺了,但是不知道為什么,這個可以直接存數(shù)據(jù)庫。
/**
把用戶輸入的文本轉(zhuǎn)義(主要針對特殊符號和emoji表情)
*/
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,因為我發(fā)現(xiàn)我很多emoji實際上是\ud開頭的,反而暫時沒發(fā)現(xiàn)有\(zhòng)ue開頭。
return json_decode($text);
}
/**
解碼上面的轉(zhuǎn)義
*/
function userTextDecode($str){
$text = json_encode($str); //暴露出unicode
$text = preg_replace_callback('/\\\\\\\\/i',function($str){
return '\\';
},$text); //將兩條斜杠變成一條,其他不動
return json_decode($text);
}
回復內(nèi)容:
unicode emoji是4個字節(jié)的,存不進MySQL里,找到一個轉(zhuǎn)義的庫http://code.iamcal.com/php/emoji/,但是轉(zhuǎn)為Unicode之后,還是4個字節(jié),一樣存不進,應該說根本沒轉(zhuǎn)。轉(zhuǎn)為其他格式的emoji又怕以后新增了表情不好做,你們在不改數(shù)據(jù)庫編碼的前提下,是怎么弄的?
方法1:base_encode64
這種方法是可以,但是舊數(shù)據(jù)沒有經(jīng)過encode操作,取數(shù)據(jù)的時候如果統(tǒng)一進行decode的話,舊數(shù)據(jù)會丟失的。
方法2:urlencode
這個似乎可以,對沒有經(jīng)過encode的數(shù)據(jù)進行decode也不會有影響,而且多次decode似乎也不會有影響。你們說這個方法有缺陷嗎?
=======================
一個發(fā)現(xiàn),微信獲取用戶基本信息的時候,笑哭那個表情print_r出的是\ud83d\ude02,而我存儲的時候,報錯說這個 \xF0\x9F\x98\x82 值不能存儲,請問這是怎么回事,自動轉(zhuǎn)碼了,轉(zhuǎn)成的這是什么?是微信轉(zhuǎn)碼過了嗎?
=======================
方法3:最后采用了下面采納的那個方法,因為我覺得它有下面幾個優(yōu)點:
1、那個方法只轉(zhuǎn)換表情,不會轉(zhuǎn)換中文,所以數(shù)據(jù)還是直接可讀的
數(shù)據(jù)庫中存儲起來是這樣的,
后面的\ud83d\udca5可以隨意復制粘貼,而顯示出來是這樣的,
2、不會把表情轉(zhuǎn)換為其它標準,只有一個簡單的,固定的轉(zhuǎn)換算法,也就是說不需要一個表情庫來對照著轉(zhuǎn)換,所以以后其它人要使用這個數(shù)據(jù)的時候,也很容易知道每個表情是對應的哪個。就算蘋果大爺又增加了表情,也不需要做什么額外的修改。
3、可以無限decode輸出的都是正確的內(nèi)容。因為有的時候可能需要在一次請求中的兩個地方做decode,其它decode多次會把正確的數(shù)據(jù)改成其它數(shù)據(jù),這個不會。
缺點:
1、看了下面的代碼就知道,這個是強制修改字符編碼中,指定區(qū)間內(nèi)的編碼,也就說有可能誤殺,也有可能有超出這個區(qū)間的emoji沒殺到。不過僅僅是在字符前加反斜杠,即使誤殺了,發(fā)現(xiàn)之后也很容易改回來。
數(shù)據(jù)庫中發(fā)現(xiàn)有這樣的
,是漏殺了,但是不知道為什么,這個可以直接存數(shù)據(jù)庫。
/**
把用戶輸入的文本轉(zhuǎn)義(主要針對特殊符號和emoji表情)
*/
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,因為我發(fā)現(xiàn)我很多emoji實際上是\ud開頭的,反而暫時沒發(fā)現(xiàn)有\(zhòng)ue開頭。
return json_decode($text);
}
/**
解碼上面的轉(zhuǎn)義
*/
function userTextDecode($str){
$text = json_encode($str); //暴露出unicode
$text = preg_replace_callback('/\\\\\\\\/i',function($str){
return '\\';
},$text); //將兩條斜杠變成一條,其他不動
return json_decode($text);
}
我是這么玩兒的
給一個標準的解決方案:
mysql的版本必須為v5.5.3或更高
把數(shù)據(jù)庫的編碼改成utf8mb4 -- UTF-8 Unicode
然后需要存儲emoji表情的字段選擇utf8mb4_general_ci
數(shù)據(jù)庫連接也需要改為utf8mb4
設置完成后,應該可以看到如下類似字符集設置結(jié)果。那么可以直接的存入數(shù)據(jù)庫,無需做任何額外的事情了。
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
rows in set (0.00 sec)
我在做微信公眾平臺開發(fā)時遇到過這個問題,微信用戶的昵稱可以包含表情(坑爹- -!)。于是我就將整個昵稱轉(zhuǎn)換成HEX字符串存在MySQL中,目前用戶1W+,系統(tǒng)穩(wěn)定,題主可以參考一下此方案。
MySQL支持hex() and unhex()函數(shù)。Java可以使用org.apache.commons.codec.binary.Hex工具類。其他語言也有相應的方法。
試試微博或qq里面的那種方式?用簡單的編碼來映射,比如微笑可以用 [wx] 或 /wx 。不過表情多了之后4個字符不怎么夠用。。。
urldecode
我看了一下 decode 的源碼,應該是不會出現(xiàn)問題。
只要沒有 % 解碼后肯定還是原來的字符(串),有 % 會出現(xiàn)兩種情況,一種是解碼成功,這個時候肯定就不是原來的字符串了,一種是解碼失敗,拋出異常(其實這個異常可以作為是否 encode的標準)。
解碼還算是比較嚴格吧,作為用戶名的情況下 出現(xiàn) % 還解碼成功的概率比較小吧,對于這部分你可以手動改數(shù)據(jù)庫,應該不會有很多。
你試試這個函數(shù),之前弄微信自定義菜單的時候,也接觸過Emoji表情,當時看到用的這個函數(shù)把Emoji表情的編碼給轉(zhuǎn)換了。
function utf8_bytes($cp) {
if ($cp > 0x10000){
# 4 bytes
return chr(0xF0 | (($cp & 0x1C0000) >> 18)).
chr(0x80 | (($cp & 0x3F000) >> 12)).
chr(0x80 | (($cp & 0xFC0) >> 6)).
chr(0x80 | ($cp & 0x3F));
}else if ($cp > 0x800){
# 3 bytes
return chr(0xE0 | (($cp & 0xF000) >> 12)).
chr(0x80 | (($cp & 0xFC0) >> 6)).
chr(0x80 | ($cp & 0x3F));
}else if ($cp > 0x80){
# 2 bytes
return chr(0xC0 | (($cp & 0x7C0) >> 6)).
chr(0x80 | ($cp & 0x3F));
}else{
# 1 byte
return chr($cp);
}
}
使用BOLO類型
將數(shù)據(jù)庫編碼改為 utf8mb4
我這個剛解決的這個問題(后端是java實現(xiàn)的,數(shù)據(jù)庫Mysql),供參考。
1、修改存儲emoji字段編碼,例如放在username字段中:
ALTER TABLE user CHANGE username username VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci default null;
2、java在執(zhí)行數(shù)據(jù)庫插入、更新操作前,要先執(zhí)行 sql語句"set names utf8mb4" 語句。
https://github.com/iamcal/php-emoji
我是用這個處理的~
http://www.emoji-cheat-sheet.com/
有一種編碼叫 utfmb4,支持 4 位長度的 utf8 編碼
喏,你的 MySQL 版本必須為 5.5 以上的
不用轉(zhuǎn),直接數(shù)據(jù)庫轉(zhuǎn)成utf8mb4, 我以前就是這么干的
不用更改整個數(shù)據(jù)庫的把。。。create xxx() charset=utf8mb4 單表 utf8mb4就行了把
因為我的項目中需要對字數(shù)有限制的需求,涉及到逐字計數(shù),在這基礎上我增加了emoji的功能完美實現(xiàn)。你需要代碼的話請再告訴我,我提供給你。
本文原創(chuàng)發(fā)布php中文網(wǎng),轉(zhuǎn)載請注明出處,感謝您的尊重!
總結(jié)
以上是生活随笔為你收集整理的php数据库插入表情转换,如何转义emoji表情,让它可以存入utf8的数据库?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq表情左右滑动php,基于jQuery
- 下一篇: 数据结构期末复习