必须修改my.ini的[mysqld]段,因mysql服务端默认字符集决定新建库表编码,xampp默认latin1或utf8mb3不支持emoji四字节字符,仅改php连接或phpmyadmin无效。

必须改 my.ini 的 [mysqld] 段,否则 emoji 存不进数据库,不是 PHP 或前端的问题。
为什么只改 PHP 连接或 phpMyAdmin 设置没用
MySQL 服务端默认字符集决定新建库/表的底层编码。XAMPP 默认是 latin1 或过时的 utf8(即 utf8mb3),它压根不支持四字节字符——emoji 就是典型四字节,存进去直接截断或报错 Incorrect string value。你就算在 PHP 里用 PDO 加了 ;charset=utf8mb4,只要服务端还是 latin1,连接一建立,character_set_database 和 character_set_server 就仍是错的,后续建表语句默认就写 CHARSET=latin1。
- 查当前真实服务端设置:连上 MySQL 后执行
SHOW VARIABLES LIKE 'character_set_server';和SHOW VARIABLES LIKE 'collation_server'; - 如果返回是
latin1或utf8,说明问题根子在配置文件,不是客户端能绕过去的 -
character_set_client、character_set_results等可以被客户端覆盖,但character_set_server只认[mysqld]段的character-set-server
改哪个文件、在哪段、写哪几行才生效
XAMPP 实际加载的配置文件是 C:\xampp\mysql\bin\my.ini(不是 conf\my.cnf,那个通常被忽略)。必须在 [mysqld] 段下添加或修改这三行:
character-set-server = utf8mb4collation-server = utf8mb4_unicode_ci-
skip-character-set-client-handshake(可选,强制客户端服从服务端设定,避免某些工具乱传字符集)
⚠️ 删掉所有带 default-character-set 的行——这个参数在新 MySQL 中已废弃,且只在 [client] 段有效,写在 [mysqld] 里会导致启动失败。也别在 [client] 或 [mysql] 段写 character-set-server,它对服务端完全无效。
重启后旧库旧表还是乱码?得手动转
改完配置并用 XAMPP 控制面板「停止 → 启动」MySQL 后,character_set_server 和 collation_server 会变成 utf8mb4,但这只影响之后新建的数据库和表。已有数据仍按原始字符集存储,导出 SQL 时建表语句还会写 CHARSET=latin1,导入到新环境照样乱码。
- 先改库:
ALTER DATABASE `your_db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 再逐张改表:
ALTER TABLE `your_table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:
CONVERT TO会重写所有字段,但不会改动字段长度定义(比如VARCHAR(255)不会变)
PHP 连接必须显式声明 utf8mb4,不能靠 SET NAMES
即使 MySQL 服务端设好了,PHP 默认仍可能用 utf8 建立连接。用 mysqli 时,在 mysqli_real_connect() 后立刻调用 mysqli_set_charset($conn, 'utf8mb4');;用 PDO 时,DSN 必须带 ;charset=utf8mb4,例如:$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass);
靠 SET NAMES utf8mb4 执行一次是不够的,尤其开启持久连接时,该命令可能被跳过。不加这个,哪怕存进去了,读出来也是乱码或问号。
真正麻烦的点不在改配置,而在于「服务端设对了 + 旧数据转完了 + PHP 连对了」这三件事必须全部到位,漏一个,emoji 就存不稳或读不出。很多人卡在第二步,以为改完 my.ini 就万事大吉,结果导出 SQL 一看,建表语句里还是 CHARSET=latin1。











