2015-01-05 19 views
2

我有一个站点接受来自用户的基于表单的输入并存储到mysql(i)数据库中。 99%的用户来自美国。可以通过utf8_decode整个SQL语句来避免utf-8/utf8mb4问题吗?

如果用户在移动设备上并决定在其中一个表单字段中使用表情符号很有趣,则在尝试更新或插入时,生成的SQL会导致失败。这是由于表情符号在utf-8之外,因此UX和数据库之间的编码不匹配。我相信我理解潜在的问题。

我在MySQL 5.5中,所以我实际上可以支持utf8mb4字符集 - 但是我需要一段时间才能解决这个问题。

在此期间,这将是确定/安全只是这样做(在PHP):

$sql = "INSERT INTO my_table ... *long insert statement across two dozen rows*"; 
$sql = utf8_decode($sql); 
$db->sql_query($sql); 

所以 - 简单地迫使整个SQL语句为UTF-8?我意识到表情符号和其他一些可能转换为“?” - 但只要声明本身没有被破坏,或者我不会丢失用户的正常文本输入,我就可以做到这一点。

这个想法的任何问题作为一个临时修复,直到我可以转换表的模式来使用utf8mb4?

编辑:从数据库中返回的错误看起来是这样的:

"Incorrect string value: '\xF0\x9F\x99\x8A...' for column..." 
+1

UTF-8涵盖了所有的Unicode,也是表情符号。但是,自从Unicode版本6.0以来,表情符号就存在了。弱点似乎更多的是没有这些字符的字体。也许可以替换'[\ u1F300- \ u1F5F]'。 –

+0

谢谢,但这会变得非常迅速。移动设备上的这些表情符号不限制在单个字符范围内。我想,我必须保留某种地图。 –

+0

@Joop如果有一个实际的错误被抛出(“失败”...?),那么这几乎不是一个字体问题。 – deceze

回答

2

一些事实:

  • 许多表情符是Unicode中的BMP(基本多文种平面)以上,即上面的代码点U + FFFF
  • MySQL的utf8字符集只能代表BMP,它实际上不是完整的UTF-8(耶的MySQL
  • 为完整的Unicode支持MySQL有utf8mb4
  • 尝试存储BMP上述字符在utf8字符集列,MySQL将简单地丢弃不支持的字符(耶无记载数据损坏
  • 时应该没有实际的错误utf8_decode不会“强制所有内容为UTF-8”,而是将字符串从UTF-8编码转换为ISO-8859-1(“Latin-1”)编码;这将丢弃更多的字符,而不仅仅是表情符号

因此,在我看来,如果您在某个时刻出现实际错误,那么您还有其他潜在问题。也许你认为你正在用UTF-8与数据库进行交谈,但实际上并非如此。您需要通过mysqli_set_charset来设置连接字符集连接字符集

“过滤掉”你的数据库不支持的字符应该已经发生了,MySQL会简单地丢弃这些字符。如果你想在PHP中手动做到这一点,你可以这样做筛选出上述U + FFFF中的所有字符:

$string = preg_replace_callback('/./u', function (array $m) { 
    return strlen($m[0]) > 4 ? null : $m[0]; 
}, $string); 

总评:支持utf8mb4大约需要两分钟。你只需要将你的表/列字符集设置为utf8mb4,并对你的mysqli连接进行相同的操作。如果您将实际的UTF-8数据从您的PHP应用程序发送到您的数据库,那么您将存储表情符号就好了。

+0

在数据库抽象层代码中发现此错误: @mysqli_query($ this-> db_connect_id,“SET NAMES'utf8'”);所以,它看起来像连接开始设置为'utf8',对吧?我查看了这些表的模式,并说表的排序规则是“utf8_bin”。这个信息是否提供了更多的线索,为什么我得到了字符串错误? –

+0

我认为即使通信和模式是utf-8,我们也会回到mysql被限制为3个字节的字符 - 并且我测试的表情符号字符是4个字节的字符。你是否同意这是什么导致错误被抛出? –

+0

使用'SET NAMES'查询而不是'mysqli_set_charset'可能是个问题。这基本上是在mysqli后面设置连接编码; mysqli并不知道你试图通过'utf8'与数据库进行通信,并且在转义数据时可能会破坏客户端的编码。 – deceze