php实现班级通信录导入表情符号_php过滤表情导入法【技巧】
技术百科
看不見的法師
发布时间:2026-01-27
浏览: 次 根本原因是MySQL默认utf8(utf8mb3)不支持4字节emoji,须统一使用utf8mb4字符集并确保连接层、表结构、配置文件均生效;过滤emoji应优先用专业库而非简单正则或iconv//IGNORE。
PHP 导入 Excel 时表情符号报错 SQLSTATE[HY000]: General error: 1366 Incorrect string value
这是最典型的症状:Excel 里有 ?、?、?? 这类 emoji,用 fgetcsv 或 PhpSpreadsheet 读取后直接插入 MySQL,就卡在字符集不兼容上。根本原因不是 PHP 读不了 emoji,而是 MySQL 默认的 utf8(实为 utf8mb3)只支持最多 3 字节字符,而大部分 emoji 是 4 字节 UTF-8 编码。
解决前提是数据库和表必须用 utf8mb4 字符集,且连接层也要显式指定:
- 建表语句加
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - PDO 连接时在 DSN 后追加
;charset=utf8mb4,或执行$pdo->exec("SET NAMES utf8mb4") - 确保 MySQL 配置文件中
collation-server = utf8mb4_unicode_ci和character-set-server = utf8mb4已生效
用 preg_replace 过滤 emoji 的实际效果很有限
网上常见写法是 preg_replace('/[\x{1F600}-\x{1F6FF}]/u', '', $str),但问题在于:emoji 范围远不止这个区间,Unicode 15.1 已定义超 3700 个 emoji,还包含组合序列(如 ?? = ? + ZWJ + ?)、变体修饰符(肤色)、国旗(?? 是两个区域指示符字符)——正则很难全覆盖,且容易误杀合法生僻汉字(比如某些 CJK 扩展区字符也在类似码位)。
更务实的做法是「保留可安全入库的字符」而非「穷举过滤」:
- 用
mb_convert_encoding($str, 'UTF-8', 'UTF-8')先做编码归一化 - 用
mb_strlen($str, 'UTF-8') === mb_strlen(utf8_encode(utf8_decode($str)), 'UTF-8')粗筛含非法字节的字符串(此法对部分边缘 case 不严谨,但够用) - 真正要过滤时,推荐用现成库如
stevegrunwell/emojione的Emoji::remove(),它基于 Unicode 官方 emoji 数据库,维护及时
iconv('UTF-8', 'UTF-8//IGNORE', $str) 会静默丢弃 emoji,慎用
这个技巧看似简单——//IGNORE 模式会让 iconv 跳过无法转换的字节,结果确实是把 emoji 去掉了。但它的问题是:不仅删 emoji,也会删掉所有其他无法映射的 UTF-8 序列(比如损坏的编码、未授权私有区字符),而且不报任何 warning,排查时完全无迹可循。
如果坚持用转换方式处理,更可控的是:
- 先用
mb_check_encoding($str, 'UTF-8')确保输入是合法 UTF-8 - 再用
mb_substr($str, 0, 255, 'UTF-8')截断(避免超字段长度),而不是依赖iconv的暴力截断 - 若业务允许替换而非删除,可用
mb_ereg_replace将 emoji 替换为占位符,如[EMOJI]
PhpSpreadsheet 读取含 emoji 的单元格需设置 setReadDataOnly(true)
默认情况下,PhpSpreadsheet 会解析公式、样式、富文本等元数据,这些额外信息可能引入不可见控制字符或编码异常,加剧 emoji 处理失败。开启 setReadDataOnly(true) 能跳过渲染逻辑,只提取纯文本值,大幅降低出错概率。
示例关键代码:
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx(); $reader->setReadDataOnly(true); $spreadsheet = $reader->load($filePath); $sheet = $spreadsheet->getActiveSheet(); foreach ($sheet->getRowIterator() as $row) { $cellIterator = $row->getCellIterator(); $cellIterator->setIterateOnlyExistingCells(false); foreach ($cellIterator as $cell) { $value = $cell->getValue(); // 此时 $value 是干净字符串,可直接 utf8mb4 入库或按需过滤 } }
真正麻烦的从来不是“怎么删表情”,而是“删完之后字段长度、空格、换行、零宽字符是否还一致”。通信录里一个隐藏的 \u200B(零宽空格)可能让姓名查重失效,比 emoji 本身更难察觉。
# 的是
# 这是
# 很难
# 也会
# excel
# 最多
# 跳过
# 而非
# 配置文件
# Error
# String
# 编码
# 字节
# 字符串
# 数据库
# 根本原因
# php
# 穷举
# office
# csv
# mysql
# pdo
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在Golang中修改数组元素_通过指针实现原地
- Python迭代器生成器进阶教程_节省内存与懒加载
- Windows Defender扫描失败怎么办_安
- php串口通信波特率怎么选_根据硬件手册设置正确波
- Win10电脑怎么设置IP地址_Windows10
- Mac自带的词典App怎么用_Mac添加和使用多语
- ACF 教程:如何正确更新嵌套在多层 Group
- Windows11如何设置专注助手_Windows
- 如何使用Golang实现微服务状态监控_Golan
- Linux怎么设置磁盘配额_Linux系统Quot
- c++中的std::conjunction和std
- Python字符串操作教程_切片拼接与格式化详解
- 如何处理“XML格式不正确”错误 常见XML we
- Win11怎么关闭自动调节亮度 Win11禁用内容
- Win11无法拖拽文件到任务栏怎么办_Win11开
- Win11怎么关闭粘滞键_彻底禁用Windows
- Win11任务栏天气怎么关闭 Win11隐藏天气小
- 如何使用Golang table-driven基准
- Win11怎么快速锁屏_Win11一键锁屏快捷键W
- Win11怎么设置任务栏大小_Windows11注
- Windows怎样拦截WPS弹窗广告_Window
- Win10闹钟铃声怎么自定义 Win10闹钟自定义
- Win11怎么开启远程桌面连接_Windows11
- 如何在Golang中实现文件下载_Golang文件
- Win11如何更新显卡驱动 Win11检查和安装设
- Bpmn 2.0的XML文件怎么画流程图
- Linux如何申请SSL免费证书_Linux下Ce
- MAC如何隐藏文件夹及文件_MAC终端命令隐藏与第
- PHP cURL GET请求:正确设置请求头与身份
- Win11怎样激活系统密钥_Win11系统密钥激活
- Win10如何备份注册表_Win10注册表备份步骤
- Python代码测试策略_质量保障解析【教程】
- Win10系统字体模糊怎么办_Windows10高
- Mac的访达(Finder)怎么用_Mac文件管理
- Windows10电脑怎么连接蓝牙设备_Win10
- Windows10如何彻底关闭自动更新_Win10
- Win10电脑C盘红了怎么清理_Windows10
- LINUX怎么进行文本内容搜索_Linux gre
- Win11视频默认播放器怎么改_Win11关联第三
- 手机php文件怎么变成mp4_安卓苹果打开php转
- Python性能剖析高级教程_cProfileLi
- C++如何编写函数模板?(泛型编程入门)
- 如何使用Golang实现基本类型比较_Golang
- Win11文件夹预览图不显示怎么办_Win11缩略
- c++的STL算法库find怎么用 在容器中查找指
- Win10文件历史记录怎么用 Win10开启自动备
- PythonFastAPI项目实战教程_API接口
- C++如何解析JSON数据?(nlohmann/j
- Windows怎样关闭锁屏广告_Windows关闭
- Dapper的Execute方法的返回值是什么意思


QQ客服