必须在php连接后立即调用mysqli_set_charset($conn, 'utf8mb4')或pdo dsn中指定charset=utf8mb4,因phpenv的mysql启动脚本常绕过my.cnf,服务端配置不强制客户端字符集,仅改配置文件无效。

phpEnv 默认不强制 MySQL 连接使用 UTF8,必须手动干预连接初始化过程,否则即使数据库和表是 utf8mb4,PHP 读写仍可能乱码。
为什么 my.cnf 设置了 utf8mb4 还是乱码?
phpEnv 中的 MySQL 配置(如 character-set-server=utf8mb4)只影响服务端默认字符集,不控制 PHP 客户端连接时的字符集协商。PHP 的 mysqli 或 PDO 在建立连接时若未显式指定,会沿用 MySQL 服务端的 collation_server(可能是 latin1_swedish_ci),导致实际连接使用非 UTF8 字符集。
- 典型现象:
SHOW VARIABLES LIKE 'character_set_client'返回latin1,哪怕数据库是utf8mb4_unicode_ci - 根本原因:phpEnv 启动的 MySQL 实例未在启动参数中注入
--collation-server=utf8mb4_unicode_ci,且 PHP 层无连接后设置 - 仅改
my.cnf不生效,因为 phpEnv 的服务脚本通常绕过该文件,或加载顺序/覆盖逻辑不一致
在 PHP 代码里用 mysqli_set_charset() 强制生效
这是最直接、兼容性最好、无需重启服务的方式,适用于所有 phpEnv 下的 PHP 版本(5.6+ / 7.x / 8.x)。
- 必须在
mysqli_connect()之后、任何查询之前立即调用 - 推荐写法:
mysqli_set_charset($conn, 'utf8mb4')(注意是utf8mb4,不是utf8) - 若用面向对象风格:
$conn->set_charset('utf8mb4') - 不要用
mysqli_query($conn, "SET NAMES utf8mb4")—— 它不保证字符集完全同步,尤其在预处理语句场景下不可靠
用 PDO 连接时必须带 charset DSN 参数
PDO 不会自动继承 MySQL 服务端字符集,mysql:host=localhost;dbname=test 这种基础 DSN 默认走 latin1。
- 正确写法:
new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass) - 错误写法:
new PDO('mysql:host=localhost;dbname=test', $user, $pass)(缺charset) - 不能靠
exec("SET NAMES utf8mb4")补救 —— 某些 phpEnv 环境下 PDO 初始化阶段已协商完毕,后续 SET 不影响编码通道 - 如果用
PDO::MYSQL_ATTR_INIT_COMMAND,需确保它在构造时传入:[PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"],但不如 DSN 参数稳定
phpEnv 自带的 MySQL 启动脚本怎么补上全局字符集?
如果你希望所有连接(包括命令行 mysql 客户端、其他语言连接)默认走 utf8mb4,需修改 phpEnv 的 MySQL 启动配置,而非仅依赖 my.cnf。
- 找到 phpEnv 的 MySQL 启动脚本,路径类似:
phpenv\mysql\bin\mysqld_start.bat(Windows)或phpenv/mysql/bin/mysqld_start.sh(Linux/macOS) - 在启动命令末尾追加:
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci - 例如 Windows bat 中修改这一行:
mysqld --defaults-file="%~dp0..\conf\my.ini" --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci - 改完后必须重启 MySQL 服务才生效;不重启的话,
SHOW VARIABLES LIKE 'character_set_server'仍显示旧值
真正容易被忽略的是:PDO 的 charset 参数必须写在 DSN 里,而不是靠后续 exec();而 phpEnv 的 MySQL 启动脚本往往硬编码了参数,my.cnf 文件可能根本不被读取——所以光改配置文件没用,得动手改启动命令本身。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











