php 8.0+ 默认 pdo 错误模式为 pdo::errmode_exception,非警告;php 7.0–7.4 默认为 pdo::errmode_silent,错误不报错、不中断,需手动检查返回值和 errorinfo()。

PHP 7.0 和 PHP 8.0 的 PDO 默认错误模式根本不是“静默 vs 警告”——PHP 8.0 默认是 PDO::ERRMODE_EXCEPTION,不是警告。 所有说“PHP 8 默认警告”的说法都是错的,容易导致配置被覆盖却没意识到问题已升级为异常中断。
PHP 7.0 默认确实是 PDO::ERRMODE_SILENT
这意味着:任何 SQL 错误(比如表不存在、字段名写错、约束冲突)都不会抛出异常或警告,exec()、query() 等方法只返回 false,且不打断脚本执行。你必须手动检查返回值,并调用 $pdo->errorInfo() 或 $stmt->errorInfo() 才能拿到错误详情。
- 常见踩坑:写完
$pdo->exec($sql)没判断返回值,结果 INSERT 失败但程序继续跑,数据“静默丢失” - 调试困难:错误信息藏在
errorInfo()数组第三项,errorInfo()[2]才是 MySQL 原始报错,新手常漏掉 - 兼容性注意:PHP 7.0–7.4 全系默认都是
SILENT,无例外
PHP 8.0+ 默认是 PDO::ERRMODE_EXCEPTION,不是 WARNING
这是关键事实,官方文档和 PHP 8.0 发布说明明确标注:从 PHP 8.0.0 开始,PDO::ATTR_ERRMODE 的默认值改为 PDO::ERRMODE_EXCEPTION。一旦出错(哪怕只是 SELECT 查了不存在的字段),直接抛 PDOException,脚本中断,除非你用 try/catch 捕获。
- 好处:错误位置精准,堆栈清清楚楚,不用每行都
if ($res === false) - 风险:没包
try/catch的旧代码,在 PHP 8 下会直接 Fatal Error,比如$pdo->query("SELECT x FROM y")表y不存在 → 报Fatal error: Uncaught PDOException: SQLSTATE[42S02]... - 注意:
PDO::ERRMODE_WARNING从未是任何 PHP 版本的默认值;它只是个中间选项,发E_WARNING但不中断流程,适合临时调试
为什么有人误以为 PHP 8 是“默认警告”?
因为部分人把连接失败时的提示(如 mysqli_connect(): php_network_getaddresses: getaddrinfo failed)或某些扩展的日志行为,错当成 PDO 的 ERRMODE_WARNING。实际上:
- PDO 连接失败(如 host 不通、密码错)永远触发
PDOException,无论 PHP 版本,__construct不受ATTR_ERRMODE控制 -
ERRMODE_WARNING只影响「已连接成功后」的 SQL 执行错误,且仅输出警告,不抛异常、不中断 - 如果你在 PHP 8 环境看到警告而非异常,大概率是代码里显式写了
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING),覆盖了默认值
跨版本安全写法:显式设置,别依赖默认
不要赌版本差异。生产环境应始终显式声明错误模式,尤其是升级 PHP 时:
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
- 这样在 PHP 7 和 PHP 8 下行为完全一致,避免静默失败或意外中断
- 如果真要降级兼容老代码,可设为
PDO::ERRMODE_SILENT,但务必补全所有if (!$res) { ... $pdo->errorInfo() ... } - 切记:
PDO::ERRMODE_EXCEPTION下事务会自动回滚,而SILENT或WARNING下需手动rollback()
最易被忽略的一点:PDO 的错误模式只管 SQL 执行,不管连接本身;连接失败永远是异常,且无法用 setAttribute 关闭。升级到 PHP 8 后,第一件事不是改语法,是检查所有 PDO 调用是否被 try/catch 包裹住。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











