MySQL 的编码问题
前几天朋友的小程序遇到点问题,同样的代码,有些人就是注册不上,有些人就没问题。让我帮忙看。
看代码应该没问题,我自己试也没问题,很诡异。后来我发现,说注册不上的一个截图里,昵称里有一个雨滴的符号。我们知道,传统的编码是没有表情符号的,表情符号是 Unicode 后期才加进去的,那么会不会是数据库字段的问题?看了一眼,Laravel 默认创建的数据库,字符类型是 utf8mb4_unicode_ci,而他们数据库是 utf8_general_ci,Google 一下,找到下面这篇文章:
為什麼MYSQL要設定用UTF8MB4編碼 UTF8MB4_UNICODE_CI
里面提到:
當資料庫需要儲存或處理以下資料:emoji (手機端常用的表情字符)
应该使用 utf8mb4_unicode_ci,因为它会用更多的空间存储字符。基本锁定是字符集的问题。然后看到梦康大的一篇博文:直接使用 mysql utf8 存储 超过三个字节的 emoji 表情 ( 不使用 utf8mb4 ),决定参考他的方案,毕竟改库改表不是小事情。
不过时过境迁,梦康文中的 func_overload 已经可以用 mb_strlen($str, '8bit') 来替代,所以最后的代码大约是这样的:
// 替换
protected function encodeEmoji($input) {
$length = mb_strlen($input, 'utf-8');
$result = '';
for ($i = 0; $i < $length; $i++) {
$tmp = mb_substr($input, $i, 1, 'utf-8');
if (mb_strlen($tmp, '8bit') >= 4) {
$result .= '[[Emoji:' . rawurlencode($tmp) . ']]';
} else {
$result .= $tmp;
}
}
return $result;
}
// 替换回
protected function decodeEmoji($nickname) {
return preg_replace_callback('~\[\[Emoji:(.*?)\]\]~', function ($matches) {
return rawurldecode($matches[1]);
}, $nickname);
}
所以说,程序员心态要保持年轻,步调要跟年轻人保持一致,这样才更容易发现新问题,所以我的昵称已经改成“肉山🎩”了。
相关文章
从40秒到11毫秒:TiDB Cloud一次SQL深潜优化实战
TiDB Cloud 一次 SQL 深潜优化实战:把一条查询从 40 秒优化到 11 毫秒。完整展示执行计划分析、索引设计与改写思路,本文获 TiDB 社区第四届专栏征文大赛二等奖。
记一次不成功的数据库搬家
我这个博客始建于 2011 年,当时我从 ZOL 离职,表达欲旺盛的我,希望找个地方继续写博客,于是就买了台集 […]
记一次 TiDB Cloud Serverless 超额导致的博客超时故障
一次真实故障复盘:TiDB Cloud Serverless 免费额度用尽导致博客 502 超时。记录从发现问题、定位到 RU 超额、上调预算恢复服务的全过程,以及后续降低数据库用量的思路,供使用 S


