PDO连接失败的四大原因:pdo_mysql扩展未启用、DSN缺charset=utf8mb4、密码含特殊字符未urlencode、未设置PDO::ATTR_ERRMODE为EXCEPTION。

pdo_mysql扩展没启用,new PDO()直接报“could not find driver”
PHP 8.5.5 已彻底移除旧的 mysql 扩展,mysqli 虽可用但不是 PDO 默认底层——PDO 必须搭配 pdo_mysql 才能工作。不启用就调 new PDO(),必然抛出 PDOException: could not find driver。
检查方法:php -m | grep pdo,输出里必须同时有 pdo 和 pdo_mysql。缺后者说明没装或没启:
- Linux/macOS:确认
php.ini含extension=pdo_mysql,且该行未被注释 - Windows:检查
php.ini是否有extension=php_pdo_mysql.dll - Docker(如
php:8.5-cli):构建时需加docker-php-ext-install pdo_mysql
DSN漏写 charset=utf8mb4,中文和 emoji 插入静默失败
MySQL 默认字符集是 latin1,DSN 不显式声明 charset=utf8mb4,连接看似成功,但后续 INSERT 含中文或 emoji 时会报 Incorrect string value,或者字段被截断——错误不在连接阶段,排查成本高。
正确写法示例:"mysql:host=localhost;dbname=testdb;charset=utf8mb4":
立即学习“PHP免费学习笔记(深入)”;
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 别用
utf8:MySQL 的utf8实际是utf8mb3,不支持 4 字节 Unicode(如 ?、??) - 即使 MySQL 配置了
collation-server = utf8mb4_unicode_ci,DSN 里仍要写charset=utf8mb4;PDO 不读服务端默认值 -
$pdo->exec("SET NAMES utf8mb4")是冗余操作,不能替代 DSN 指定
密码含 @ / : ? 等字符,DSN 解析错位导致连错主机或用户
DSN 是 URL 风格字符串,@、/、:、? 会被解析为分隔符。比如密码是 pa@ss/word,拼成 mysql:host=localhost;user=root;pass=pa@ss/word 就会把 ss/word 当成 host。
安全做法是单独对密码做 urlencode():
- 传参时:用
urlencode($password),再塞进new PDO($dsn, $user, $encoded_pass) - 空密码必须传
"",不能传null,否则触发TypeError - 绝对不要在 DSN 字符串里直接插变量,如
"password={$pass}"——没转义就崩
PDO 默认不抛异常,错误被吞掉,调试时完全看不到真实报错
默认情况下,new PDO() 连接失败只返回 false,query() 出错也只返回 false,没有任何提示。你可能以为代码跑通了,其实表不存在、字段名写错都悄无声息。
必须手动开启异常模式:
- 立即执行:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) - 这句得在
new PDO()之后、任何查询之前调用 - 配合
try/catch才能捕获真实错误,比如SQLSTATE[42S02]: Base table or view not found
字符集、密码转义、扩展启用、异常模式——四个点缺一不可,少一个都会让连接行为变得不可控,尤其在生产环境里,错得越晚越难定位。


















