You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP过滤JavaScript存储字符串中的Emoji失效,忽略了什么?

问题核心:Unicode代理对的编码差异

你的示例字符串"foo \ud83d\ude08 bar"在PHP中并不是一个完整的Emoji字符,而是两个独立的UTF-16代理对字符(\ud83d是高代理项,\ude08是低代理项)。Emoji属于Unicode补充平面(代码点大于0xFFFF),在UTF-16中需要用两个代理项组合表示,但PHP的preg_replace加/u修饰符时,是按UTF-8单字符解析的,这两个代理项会被当成独立的无效UTF-8序列,所以你的正则(匹配单个补充平面字符\x{1F600}-\x{1F64F})根本匹配不到。

另外还要确认你数据库中存储的字符串格式,分两种情况解决:

情况1:数据库存的是JavaScript风格的Unicode转义文本

如果数据库里的内容是foo \ud83d\ude08 bar(即\ud83d\ude08是作为\u开头的转义字符串存储,而非实际的Emoji字符),首先需要把这些转义序列解码成真正的UTF-8字符,再过滤:

// 用json_decode快速解码JavaScript的Unicode转义序列
$decoded_text = json_decode('"' . addcslashes($text, '"\\') . '"');

// 过滤Emoji(覆盖主流Emoji Unicode区块)
$result = preg_replace('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F1E0}-\x{1F1FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u', '', $decoded_text);

情况2:数据库存的是UTF-16代理对的UTF-8编码

如果数据库里的内容是代理对转成UTF-8后的字节序列(比如\ud83d转成UTF-8是\xed\xa0\xbd,\ude08转成UTF-8是\xb8\x88),则需要直接匹配代理对的组合,或者同时匹配代理对和单平面Emoji:

// 方法1:直接匹配所有UTF-16代理对(对应所有补充平面字符,包括Emoji)
$result = preg_replace('/[\x{D800}-\x{DBFF}][\x{DC00}-\x{DFFF}]/u', '', $text);

// 方法2:精确匹配Emoji,同时覆盖代理对和基础平面的Emoji
$result = preg_replace('/(?:[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F1E0}-\x{1F1FF}\x{1F900}-\x{1F9FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]|[\x{D800}-\x{DBFF}][\x{DC00}-\x{DFFF}])/u', '', $text);

验证字符串格式的方法

可以用bin2hex($text)查看字符串的实际字节:

  • 如果输出包含5c75643833645c7564653038,说明是转义后的字符串(对应\ud83d\ude08的ASCII编码),对应情况1。
  • 如果输出包含eda0bdb888,说明是代理对的UTF-8编码,对应情况2。

内容的提问来源于stack exchange,提问作者Insomnia88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:17:00