根本原因是客户端、连接层、表结构三者字符集不一致,必须逐层对齐utf8mb4;需检查并统一character_set_server、数据库创建语句、pdo连接dsn中的charset=utf8mb4、以及表和字段的default charset=utf8mb4。

PHP8连接MySQL数据库时出现中文显示为问号、方块或乱码字符,根本原因是客户端、连接层、表结构三者字符集不一致,必须逐层对齐utf8mb4。
检查MySQL服务器默认字符集
登录MySQL命令行,执行:SHOW VARIABLES LIKE 'character_set%';
重点关注 【character_set_server】 和 【collation_server】 是否为 utf8mb4 和 utf8mb4_0900_ai_ci(MySQL 8.0+ 默认)。若不是,需修改 my.cnf 配置并重启服务;未重启前所有后续操作都无法生效。
创建数据库时显式指定字符集
不要依赖服务器默认值,建库时强制声明:
CREATE DATABASE myapp CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;
这一步漏掉会导致后续所有表继承错误的字符集,即使PHP连接设对也白搭。
PHP8中设置PDO连接字符集
方法一:DSN中直接追加 charset 参数(推荐)
$pdo = new PDO('mysql:host=localhost;dbname=myapp;charset=utf8mb4', $user, $pass);
方法二:连接后立即执行 set names(兼容旧写法,但不如方法一可靠)
$pdo = new PDO('mysql:host=localhost;dbname=myapp', $user, $pass);<br>$pdo->exec("SET NAMES utf8mb4");
注意:仅在 DSN 中写 charset=utf8 是无效的——PHP8 的 MySQLnd 驱动已弃用 utf8,只认 utf8mb4;写错会静默降级,中文仍乱码。
确保数据表与字段使用 utf8mb4
第一步:确认现有表字符集
SHOW CREATE TABLE users; 查看输出中 ENGINE 前是否有 DEFAULT CHARSET=utf8mb4。
第二步:批量转换已有表(执行前务必备份)
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
第三步:为新字段单独指定(如添加中文备注字段)
ALTER TABLE users ADD COLUMN remark VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
如果表中已有乱码数据,CONVERT 不会修复——它只改变元信息,原字节未重解码。乱码数据需从备份恢复或人工清洗。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











