mysql必须使用utf8mb4字符集,否则emoji会因utf8mb3不支持4字节字符而被截断或报错;需确保服务端、连接层、字段定义三者均为utf8mb4,并注意索引长度限制与php编码设置。

MySQL必须用utf8mb4字符集,否则存不进emoji
PHP本身能正常处理emoji字符串,问题出在数据库连接和表结构上。只要MySQL服务端、连接层、字段定义三者中任一环还是utf8(即utf8mb3),emoji就会被截断成问号或空格,甚至报错Incorrect string value。
- 检查MySQL版本:5.5.3+才支持
utf8mb4,老版本要升级 - 确认
character_set_server和collation_server已设为utf8mb4和utf8mb4_unicode_ci - 建表时显式指定:
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,别依赖默认值 -
ALTER TABLE改已有表时,必须同时改列、索引、连接编码,漏一个都白改
PHP连接MySQL时要显式设置charset为utf8mb4
哪怕MySQL服务端配置对了,PHP的PDO或mysqli连接默认仍可能走utf8,导致传输过程把4字节emoji当非法字符丢弃。
- PDO连接加
charset=utf8mb4到DSN里:mysql:host=localhost;dbname=test;charset=utf8mb4 - mysqli连接后立刻执行
$mysqli->set_charset('utf8mb4'),不能只靠配置文件 - 不要用
mysql_query("SET NAMES utf8")——它只设utf8,不是utf8mb4 - 如果用Laravel等框架,检查
config/database.php里的charset和collation是否明确写了utf8mb4
PHP内部处理emoji不需要特殊函数,但要注意strlen和json_encode
PHP 7.2+原生支持UTF-8,mb_*系列函数(如mb_strlen)能正确计数emoji,但基础函数会出错。
-
strlen()按字节算,一个emoji占4字节,结果是4而不是1;该用mb_strlen($str, 'UTF-8') -
json_encode()默认把非ASCII字符转义成\uXXXX,emoji会被打散;加JSON_UNESCAPED_UNICODE标志:json_encode($data, JSON_UNESCAPED_UNICODE) - 表单提交时,确保HTML页面声明
<meta charset="UTF-8">,否则浏览器可能用GBK编码发送 - 用
mb_check_encoding($str, 'UTF-8')做兜底校验,防止前端传入乱码
线上环境最容易漏掉的是索引长度限制
utf8mb4字符最多占4字节,而InnoDB默认单列索引最大长度是767字节,换算下来只能索引191个utf8mb4字符。超过就建索引失败,或者INSERT时报错Specified key was too long。
- 改表前先调大
innodb_large_prefix(MySQL 5.7+默认开启,5.6需手动开) - 调整
innodb_file_format = Barracuda和innodb_file_per_table = ON - 建索引时显式限制长度:
INDEX idx_name (title(191)),别直接INDEX (title) - 迁移旧表时,
SHOW CREATE TABLE查原索引定义,再手工适配长度,自动化脚本常忽略这点
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











