PHP查询MySQL乱码主因是字符集不一致,需统一服务端、数据库、表、字段及PHP连接层为utf8mb4,并在PHP中显式设置charset=utf8mb4。

PHP 查询 MySQL 返回乱码,核心原因几乎总是字符集不一致,不是 PHP 本身“出错”,而是连接层、表结构、客户端三者之间编码没对齐。先确认 utf8mb4 是当前唯一稳妥选择,utf8(MySQL 中实际是 utf8mb3)不支持 emoji 和部分生僻汉字,强行用会丢数据或变问号。
检查 MySQL 服务端默认字符集
乱码常始于 MySQL 启动时没设对全局编码。登录 MySQL 执行:
SHOW VARIABLES LIKE 'character_set%';
重点关注:character_set_server 和 collation_server。理想值应为 utf8mb4 和 utf8mb4_unicode_ci。若不是,需修改 MySQL 配置文件(如 /etc/mysql/my.cnf 或 my.ini),在 [mysqld] 段加入:
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
改完必须重启 MySQL 服务,仅 reload 不生效。
立即学习“PHP免费学习笔记(深入)”;
确认数据库、表、字段的字符集
即使服务端设对了,旧库/表可能仍是 latin1 或 utf8。用以下语句查具体对象编码:
SHOW CREATE DATABASE `your_db`;
SHOW CREATE TABLE `your_table`;
如果结果里显示 CHARSET=latin1 或 CHARSET=utf8,必须转换:
- 库级转换:
ALTER DATABASE `your_db` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 表级转换:
ALTER TABLE `your_table` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 注意:
CONVERT TO会重写所有字段,含TEXT、VARCHAR等;但不会自动改ENUM或SET的枚举值编码,需手动处理
PHP 连接时显式设置字符集
靠 MySQL 配置“自动继承”不可靠,PHP 每次连接都应主动声明。用 mysqli 时,在 new mysqli() 后立刻调用:
$mysqli = new mysqli($host, $user, $pass, $db);
$mysqli->set_charset('utf8mb4');
用 PDO 时,DSN 中必须包含 ;charset=utf8mb4:
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
漏掉这步,即使表和服务器都是 utf8mb4,PHP 仍可能以 latin1 解析返回内容,导致中文变乱码。PDO 的 setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8mb4") 是过时写法,优先用 DSN 参数。
浏览器或调试工具的响应头干扰
有时数据本身正确,但浏览器按错误编码渲染。检查 HTTP 响应头是否含 Content-Type: text/html; charset=iso-8859-1 类似内容。PHP 脚本开头加:
header('Content-Type: text/html; charset=utf-8');
同时确保 HTML 页面有正确 meta 声明:。注意:这里用的是 UTF-8(标准写法),不是 utf8 或 utf8mb4 —— 浏览器不认识后两者。
最易被忽略的是:表字段定义里指定了 CHARSET latin1,而建表语句又没显式写 CHARSET=utf8mb4,此时即使数据库默认是 utf8mb4,该字段仍继承 latin1。务必逐层检查,不能只看顶层配置。











