mysql服务端默认编码必须为utf8mb4,需检查character_set_server和collation_server变量,修改my.cnf并重启;thinkphp须显式配置charset;表与字段也需转为utf8mb4;mysqldump导出导入要指定--default-character-set=utf8mb4。

确认 MySQL 服务端默认编码是否为 utf8mb4
乱码往往不是 PHP 层的问题,而是 MySQL 实际存储时用了 latin1 或 utf8(非 utf8mb4)。SHOW VARIABLES LIKE 'character_set_server' 和 SHOW VARIABLES LIKE 'collation_server' 必须返回 utf8mb4 和 utf8mb4_unicode_ci。如果返回 latin1 或 utf8,光改 ThinkPHP 配置没用。
- 修改
/etc/mysql/my.cnf(或/etc/my.cnf),在[mysqld]下加:[mysqld]<br>character-set-server = utf8mb4<br>collation-server = utf8mb4_unicode_ci
- 重启 MySQL:
sudo systemctl restart mysql(Debian/Ubuntu)或sudo systemctl restart mysqld(CentOS/RHEL) - 注意:旧版本 MySQL(如 5.5)不支持
utf8mb4,需升级或降级适配
ThinkPHP 数据库连接配置必须显式指定 charset
ThinkPHP 默认不会强制设置连接层编码,即使数据库是 utf8mb4,PHP 的 PDO 连接仍可能走系统默认(比如 latin1)。必须在数据库配置里写死 charset。
- ThinkPHP 6.x 在
config/database.php中的connections.mysql下添加:'charset' => 'utf8mb4',
- ThinkPHP 5.x 在
database.php的'params'数组中加入:PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
- 别信“数据库设了就行”,PDO 连接初始化命令不发,客户端和服务器之间依然按默认字符集协商
检查数据表与字段实际编码是否为 utf8mb4
数据库服务端、连接配置都对了,但表或字段仍是 utf8 或 latin1,插入中文照样乱码或截断(尤其 emoji)。
- 查某张表编码:
SHOW CREATE TABLE <code>user;,看DEFAULT CHARSET和各字段的COLLATE - 批量转表:
ALTER TABLE <code>userCONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:
utf8在 MySQL 里实际是utf8mb3,不支持 4 字节 UTF-8 字符(如 ?、?),必须用utf8mb4
Linux 系统 locale 与 PHP 环境无关,但影响 mysqldump 导入行为
如果你用 mysqldump 导出再导入到 Linux,而导出机是 Windows 或 macOS,且没指定编码,dump 文件本身可能含乱码字节,再怎么配 PHP 和 MySQL 都救不回来。
- 导出时务必加:
mysqldump --default-character-set=utf8mb4 -u root -p db_name > dump.sql - 导入前检查 dump.sql 开头是否有
SET NAMES utf8mb4;没有就手动加一行 - Linux 终端的
LANG(如en_US.UTF-8)只影响终端显示,不影响 MySQL 存储逻辑,不必强行改成中文 locale
SHOW CREATE TABLE 一看字段还是 utf8,或者 mysqldump 导入后 select 出来是问号——这些地方不逐层验证,问题会藏得很深。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










