PDO :: ERRMODE_EXCEPTION不会禁止警告

时间:2018-02-08 10:01:08

标签: php mysql pdo

http://php.net/manual/en/pdo.error-handling.php

  

PDO :: ERRMODE_WARNING

     

除了设置错误代码外,PDO还会发出传统的E_WARNING消息。如果您只是想在不中断应用程序流程的情况下查看发生的问题,此设置在调试/测试期间非常有用。

     

PDO :: ERRMODE_EXCEPTION

     

除了设置错误代码之外,PDO还会抛出PDOException并设置其属性以反映错误代码和错误信息。此设置在调试期间也很有用,因为它会在错误点处有效地“炸毁”脚本,非常快速地指向代码中的潜在问题区域(请记住:如果异常导致事务,事务会自动回滚脚本终止)。

     

异常模式也很有用,因为您可以比使用传统的PHP样式警告更清楚地构建错误处理,并且使用较少的代码/嵌套,而不是在静默模式下运行并显式检查每个数据库调用的返回值。

然而,代码:

$connection = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '***');
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$connection->query('SET wait_timeout=1;');
sleep(2);

try {
    $connection->query('SELECT 1;');
} catch (\Exception $e) {
    echo sprintf('Caught %s exception: %s', get_class($e), $e->getMessage()) . PHP_EOL;
}

触发警告:

PHP Warning:  PDO::query(): MySQL server has gone away in pdo.php on line 13
PHP Warning:  PDO::query(): Error reading result set's header in pdo.php on line 13
Caught PDOException exception: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away

重要提示:问题不在于MySQL服务器的问题,而在于PDO错误处理问题。

更新:在所有三种模式下触发的警告:ERRMODE_SILENT,ERRMODE_WARNING,ERRMODE_EXCEPTION

PHP 7.2.1 (cli) (built: Jan  5 2018 17:34:14) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies

2 个答案:

答案 0 :(得分:5)

我敢说这是一个错误。我找到了两张相关的门票:

  • Bug #63812:PDO触发警告无论2012年为PHP / 5.3.19提交的错误处理策略
  • Bug #74401:PDO触发警告已设置抛出异常,于2017年提交PHP / 7.0.17

在任何情况下,它们仍然是开放的,并且它们是否是有效问题并不完全清楚(尽管我怀疑它们是否存在)。它似乎不是一个设计决策,因为其他MySQL错误不会触发,警告和异常:

$connection = new PDO('mysql:host=127.0.0.1;dbname=test', 'test', 'test',
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING]);
$connection->query('SELECT * FROM foo');
  

警告:PDO :: query():SQLSTATE [42S02]:找不到基表或视图:1146表' test.foo'不存在

$connection = new PDO('mysql:host=127.0.0.1;dbname=test', 'test', 'test',
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$connection->query('SELECT * FROM foo');
  

致命错误:未捕获的异常' PDOException'消息' SQLSTATE [42S02]:未找到基表或视图:1146表' test.foo'不存在'

答案 1 :(得分:0)

PDO::ERRMODE_EXCEPTION的目的不是为了防止php警告,通知或类似的事情 正如您可以阅读自己已经提供的文档一样,它会引发异常,而不是在结果中静默编写mysql错误。
因此,不是手动检查结果是否有错误(mysql已经消失,你有语法错误......等),PDO将直接抛出一个你可以捕获的异常。
正如您的代码所证明的那样,PDO::ERRMODE_EXCEPTION正是这样做的 您必须区分仍将显示的php错误,警告等,以及将转换为异常而不是保存在结果中的mysql错误。