php 8.5.5 用 pdo 连 mysql 必须显式指定 dsn 中的 host、dbname、charset=utf8mb4(非 utf8)、port(若非默认),且 dsn 无空格;必须设置 pdo::attr_errmode => pdo::errmode_exception,密码含特殊字符需 rawurlencode() 编码。

PHP 8.5.5 中用 PDO 连 MySQL,核心就是写对 DSN 字符串——错一个分号、少一个 charset、端口没显式声明,都可能连不上或乱码。
DSN字符串必须包含host、dbname和charset
PHP 8.5.5 默认要求显式指定字符集,否则可能触发警告或连接后读写中文出错。DSN不能只写 "mysql:host=localhost;dbname=test",得补上 charset=utf8mb4:
$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4";
-
charset=utf8mb4是强制项,不是可选;utf8在 MySQL 里实际是utf8mb3,不支持 emoji 和部分生僻字 - 如果 MySQL 服务监听非默认端口(比如 3307),必须显式加
port=3307,否则PDO不会自动探测 - DSN 中不能有空格,
;前后也不能有空格,否则PDO解析失败,报错SQLSTATE[HY000] [2002] No such file or directory(尤其在 Docker 或 socket 连接时)
连接时必须设置 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
PHP 8.5.5 对错误处理更严格,不设异常模式的话,PDO 失败只返回 false,但不会抛出具体错误,你只能看到空白页或 500 错误,查不到原因。
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
- 漏掉
PDO::ATTR_ERRMODE会导致连接失败时静默失败,调试成本陡增 -
PDO::ATTR_DEFAULT_FETCH_MODE不是必须,但设成PDO::FETCH_ASSOC能避免后续每次调用fetch()都要手动指定类型 - 别把选项数组传错位置:第三个参数是
$options,不是第二个;传错会直接报Fatal error: Uncaught TypeError
密码含特殊字符时必须 URL 编码
如果 MySQL 密码里有 @、/、:、? 这类字符,不编码就会被 DSN 解析器截断。例如密码是 p@ss/w0rd?123,直接拼进 DSN 会当成 host 或 port 的一部分。
$password = rawurlencode('p@ss/w0rd?123');
$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4";
$pdo = new PDO($dsn, $username, $password, $options);
- 只对密码做
rawurlencode(),用户名和 DSN 其他部分不用 -
urlencode()和rawurlencode()输出不同:rawurlencode()把空格转成%20,urlencode()转成+,PDO 只认前者 - 测试时可以先用简单密码(如
test123)排除语法问题,再换复杂密码验证编码逻辑
最易被忽略的是:PHP 8.5.5 下,即使 DSN 语法全对、账号密码正确,如果 MySQL 用户没被授权从 PHP 所在主机(比如 www-data@172.18.0.3)登录,也会报 Access denied —— 这个错误来自 MySQL 服务端,和 DSN 写法无关,得去 MySQL 里查 SELECT user, host FROM mysql.user; 确认权限。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











