dna*_*nag 10 php mysql error-handling pdo exception
TLDR:有谁知道具体的情况下,除了下面所示的一个,其中PDO::exec(),PDO::query(),PDO::prepare(),或PDOStatement::execute()可返回尽管没有引发异常错误,PDO::ATTR_ERRMODE被设置为PDO::ERRMODE_EXCEPTION?
我正在尝试决定是否要为我前面编写的每个数据库查询添加false检查,或者这是多余的.
编辑:我目前只使用MySQL,但如果可移植性是一个因素,这可能足以作出决定.PDO::ATTR_EMULATE_PREPARES => FALSE如果重要,我会使用.
这是我提到的具体情况.如果您准备一个包含0个或多个占位符(任一类型)的语句,然后提供一个参数数组,PDOStatement::execute()其元素多于占位符,false则返回时不会抛出异常.请注意,如果PDOStatement::bindValue()使用,则执行成功(并且只有额外绑定失败).使用比占位符少的参数会引发异常,无论参数是通过数组提供给execute函数还是使用PDOStatement::bindValue()/ 绑定PDOStatement::bindParam().
// Execute returns false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config");
if($so->execute(['Test']) === FALSE) echo '1. False returned <br />';
// Execute does not return false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config");
if($so->bindValue(1, 'Test') === FALSE) echo '2. Binding failed <br />';
if($so->execute() === FALSE) echo '2. False not returned <br />';
// Execute returns false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config WHERE webmaster_name = ?");
if($so->execute(['Test', 'Wee']) === FALSE) echo '3. False returned <br />';
// Execute does not return false, no exception thrown
$so = $rh->pdo->prepare("SELECT * FROM config WHERE webmaster_name = ?");
$so->bindValue(1, 'Test');
if($so->bindValue(2, 'Wee') === FALSE) echo '4. Binding failed <br />';
if($so->execute() === FALSE) echo '4. False not returned <br />';
Outputs:
1. False returned
2. Binding failed
3. False returned
4. Binding failed
Run Code Online (Sandbox Code Playgroud)
在select语句中,在这种情况下依赖异常并不是特别危险,因为如果您尝试调用fetch方法FALSE而不是PDOStatement对象,则无论如何都会发生错误.但是如果不进行错误检查,有一些查询,如INSERTS或UPDATES,可能会无声地失败.
我一直在学习PDO,我正在努力决定未来的错误处理的一般实践.
我肯定更喜欢异常,因为我已经拥有一个可以针对不同场景配置的良好的站点范围处理程序.而且似乎使用异常意味着更少的输入,因为您不必显式检查许多PDO函数的返回.
或者你呢?(提示戏剧性的音乐)
当我在阅读时,我遇到了不止一次提到的PDO函数(不是提取的变种),返回false而没有抛出异常.
我的问题是,是否最佳做法是检查这些功能的返回,或者是否大多数人认为是矫枉过正.
我在SO上看到了许多相互矛盾的陈述.我在一方看到了许多陈述:"PDO异常是可靠的"; "如果返回FALSE,将永远抛出PDO异常"(由人们说"我认为是真的").
这些是让我想知道的一些评论,尽管除了我提到的那个之外我还没有看到一个具体的例子.
从Can PDO方法失败并且不抛出PDOException?:
我似乎无法从一些测试用例复制这种情况(我关闭了仿真模式).
- "(Ryan Vincent)当模拟是假的时候......绑定类型是不正确的.有时可能不会抛出异常."
这一个似乎被驳斥了?我不确定如何测试这个.
- "(Xorifelse)现在提交失败,我认为有一种情况会导致它返回
false而不会抛出异常,这是在连接到数据库之后和调用之前连接到服务器时PDO::commit,很好知道是否你有一个远程数据库服务器.所以要回答你的问题,是的,它可以在不抛出异常的情况下失败,但如果你有一个本地数据库,它的时间必须非常具体."
这是我遇到的唯一可以复制的特定场景(见上文).
- "(Niksac)我已经看到了
execute()返回false而没有抛出异常,这在我看来是一种意外/不良行为.这意味着我们基本上必须同时做两件事 - 并行处理错误和异常处理.在我的情况下:如果我准备了一个插入查询没有任何参数然后用参数执行.执行不会抛出异常但返回false."
- "(castis)
$stmt->execute()绝对可以在false不抛出异常的情况下返回."
我想我发现至少有一个非特定的提及它是可能的(错误返回,没有例外),虽然我不能再追踪它们.
通过在线浏览PDO教程,大多数教程都不会在使用异常模式时检查返回.但我确实遇到过几个推荐它的人.
我描述的案例不是我在日常使用中可能搞砸的事情.或者,如果我搞砸了,我应该马上找出来.如果我在查询中动态构建占位符或参数的数量,我会知道在这种情况下确保计数匹配和/或检查错误.
如果不是真的有必要,我只是不想检查每次使用执行,查询等的返回.如果我提到的例子是唯一已知的案例,我会觉得从大多数查询中删除错误检查,这将允许我做更多的方法链接:
$user_info = $rh->pdo->query("SELECT * FROM users WHERE user_id = 1")->fetch();
// vs
$so = $rh->pdo->query("SELECT * FROM users WHERE user_id = 1");
if($so === FALSE) // Throw an exception
$user_info = $so->fetch();
Run Code Online (Sandbox Code Playgroud)
我想我正在寻找的是来自更有经验的开发人员的一些保证,可以绕过这个检查,因为我看到人们这样做.无论是那个,还是人们告诉我他们是如何通过绕过那个支票来烧掉他们的.
根据您使用的数据库,肯定会有不同的问题。如果可移植性是一个问题,我不会依赖上面您似乎发现的一些可能是 MySQL 的特性。
例如有这些: