根本原因是json_encode()不支持四字节UTF-8字符(如Emoji),PHP 7.2+可用JSON_INVALID_UTF8_SUBSTITUTE避免崩溃,稳妥方案是先用mb_convert_encoding或iconv过滤损坏字节,生产环境可正则剔除四字节字符。

PHP 中 json_encode() 报错 “Invalid UTF-8 sequence” 怎么办
根本原因不是 Emoji 本身有问题,而是 PHP 默认的 json_encode() 不接受四字节 UTF-8 字符(即大多数 Emoji),会直接返回 false 并触发警告。不改编码逻辑,光加解析器没用。
- 临时方案:用
JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE(PHP 7.2+)让非法字符被替换为 ,避免崩溃,但丢失原始 Emoji - 稳妥方案:先用
mb_convert_encoding($str, 'UTF-8', 'UTF-8')或iconv('UTF-8', 'UTF-8//IGNORE', $str)过滤掉损坏字节,再 encode - 生产环境推荐预处理:用
preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str)剔除四字节字符(适用于不需要 Emoji 的场景)
用 username_1/emoji 解析 Emoji 时为什么 toShort() 返回空?
这个库默认只处理标准 Unicode Emoji(如 ❤️、?),对 ZWJ 序列(如 ??、?❤️?)或带修饰符的(如 ??♂️)支持有限,且依赖输入字符串编码必须是完整 UTF-8 —— 如果之前被截断或转码过,toShort() 就无法匹配。
- 检查输入是否真为 UTF-8:
mb_check_encoding($str, 'UTF-8'),否则先mb_convert_encoding($str, 'UTF-8', 'auto') - 启用扩展模式:构造
EmojiParser时传入['enable_zwj' => true, 'enable_skin_tones' => true] - 别直接传
$_POST值:Web 表单提交可能含 HTML 实体(如😂),需先用html_entity_decode()转回 Unicode
MySQL 存 Emoji 必须改 utf8mb4,但改完还是乱码?
只改表字符集不够。从客户端到服务端,每个环节都得对齐 utf8mb4,漏一个就会退化成问号或 Mojibake。
- 连接层:PDO DSN 加
;charset=utf8mb4,或执行SET NAMES utf8mb4 - 字段级:确认是
VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,不是utf8 - 配置文件:
my.cnf中collation-server = utf8mb4_unicode_ci和init-connect='SET NAMES utf8mb4'缺一不可 - 验证方式:插入 ? 后用
SELECT HEX(content) FROM table查结果,应为F09F8C8D(4 字节),而非EFBFBD( 的编码)
JavaScript 前端显示 Emoji 错位或截断,比如 ?? 变成 ??
这是 JS 字符串按 UTF-16 码元计数导致的典型问题。Emoji ZWJ 序列本质是多个码点组合,.length 或 .substring() 会切在中间,破坏序列结构。
- 别用
str.substring(0, 10)截取:改用Array.from(str).slice(0, 10).join(''),它能正确识别代理对和 ZWJ 序列 - 正则匹配要加
u标志:/./gu才能匹配完整 Emoji,否则/./g会把 ?? 拆成 5 个“字符” - 服务端返回前做长度校验:如果业务限制 20 字符,JS 端应传
Array.from(str).length给后端,而不是str.length
Emoji 处理真正的难点不在“怎么加库”,而在于 UTF-8、UTF-16、数据库编码、HTTP 传输这四层之间始终维持语义一致 —— 任意一层脱节,Emoji 就会变成不可逆的乱码。











