根本原因是数据库层、连接层、客户端层字符集未统一为utf8mb4;必须在mysqli实例化后立即调用set_charset("utf8mb4"),PDO需在DSN中显式声明charset=utf8mb4,并确保库、表、字段均设为utf8mb4。

PHP 7.2 连接 MySQL 时出现中文乱码,根本原因不是 PHP 版本问题,而是字符集在「数据库层」「连接层」「客户端层」三者未对齐。只要这三层统一为 utf8mb4,乱码基本消失。
mysqli 连接后必须调用 set_charset()
PHP 7.2 的 mysqli 默认不自动协商字符集,即使数据库本身是 utf8mb4,连接仍可能回落到 latin1 —— 这是最常见的漏点。
- 必须在
new mysqli()实例化之后、执行任何查询之前调用$mysqli->set_charset("utf8mb4") - 不能只靠
CREATE DATABASE ... CHARSET utf8mb4或表结构设置,连接层不设等于白设 - 若用
mysqli_connect()函数方式,第 7 个参数可传字符集(如"utf8mb4"),但不如对象方式直观可靠
PDO 连接字符串里必须显式声明 charset=utf8mb4
用 PDO 时,仅靠 PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4" 不够稳 —— 某些 MySQL 服务端版本或配置下,SET NAMES 可能被忽略或延迟生效。
- DSN 中直接写死字符集:
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4'; - 同时保留
PDO::MYSQL_ATTR_INIT_COMMAND作为双保险(尤其面对旧版 MySQL) - 注意:不要写成
utf8—— MySQL 的utf8实际只支持 BMP 字符(不含 emoji 等四字节字符),必须用utf8mb4
检查数据库和表是否真用了 utf8mb4
很多人改了 PHP 连接,但数据库或表仍是 utf8 或 latin1,导致插入/读取时二次转码出错。
立即学习“PHP免费学习笔记(深入)”;
- 查库字符集:
SHOW CREATE DATABASE your_db;,确认DEFAULT CHARACTER SET utf8mb4 - 查表字符集:
SHOW CREATE TABLE your_table;,字段定义里应含CHARACTER SET utf8mb4 - 如果已有表是
utf8,用ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:
CONVERT TO会重写所有字段,线上表需评估锁表影响
最容易被跳过的环节是「表字段级字符集」——哪怕库和表都设对了,单个 VARCHAR 字段若建表时没指定 CHARACTER SET utf8mb4,它仍可能继承旧默认值。PHP 7.2 不会帮你兜底,每个环节都得亲手核对。



















