异常模式下的 PHP PDO - 仍然需要检查执行函数(和其他函数)的返回?

标签 php mysql exception pdo error-handling

TLDR:除了下面显示的情况之外,还有没有人知 Prop 体情况,其中PDO::exec() , PDO::query() , PDO::prepare() , 或 PDOStatement::execute()尽管 PDO::ATTR_ERRMODE 可以返回 false 而不抛出异常被设置为 PDO::ERRMODE_EXCEPTION ?

我正在尝试决定是否要为我以后编写的每个数据库查询添加一个 false 检查,或者这是否是多余的。

编辑:我目前只使用 MySQL,但如果可移植性是一个因素,这可能足以作为决定的基础。我用 PDO::ATTR_EMULATE_PREPARES => FALSE如果这很重要。

这就是我提到的具体案例。如果你准备一个带有 0 个或多个占位符(任一类型)的语句,然后向 PDOStatement::execute() 提供一个参数数组。元素多于占位符,false不抛出异常就返回。请注意,如果 PDOStatement::bindValue() 执行成功(并且只有额外的绑定(bind)失败)改为使用。使用少于占位符的参数确实会引发异常,无论参数是通过数组提供给执行函数还是使用 PDOStatement::bindValue() 绑定(bind)/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

在 select 语句中,在这种情况下依赖异常并不是特别危险,因为如果您尝试在 FALSE 上调用 fetch 方法,无论如何都会发生错误。而不是 PDOStatement目的。但是,如果您不进行错误检查,诸如 INSERTS 或 UPDATES 之类的查询可能会默默地失败。

我一直在学习 PDO,我正在尝试决定 future 错误处理的一般做法。

我绝对更喜欢异常(exception),因为我已经有一个很好的站点范围的处理程序,可以针对不同的场景进行配置。并且似乎使用异常意味着更少的输入,因为您不必显式检查许多 PDO 函数的返回。

还是你? (提示戏剧音乐)

当我阅读时,我发现不止一次提到 PDO 函数(不是获取类型)返回 false 而没有抛出异常。

我的问题是检查这些函数的返回是否被认为是最佳实践,或者大多数人是否认为这是矫枉过正。

我在 SO 上看到了很多相互矛盾的陈述。我在一方面看到了许多声明:“PDO 异常是可靠的”; “当返回 FALSE 时,总是会抛出 PDO 异常”(由说“我认为是真的”的人投票赞成)。

这些是一些让我感到疑惑的评论,尽管除了我提到的那个之外,我还没有看到一个具体的例子。

来自 Can PDO methods fail and not throw PDOException? :

我似乎无法从几个测试用例中复制这个场景(我关闭了仿真模式)。

  1. "(Ryan Vincent) when emulates is false and ... binding types are incorrect. It may not throw an exception sometimes."


这个好像被反驳了?我不知道如何测试这个。

  1. "(Xorifelse) Now for committing to fail, I believe there is 1 scenario that would cause it to return false without throwing an exception and that is when the connection to the server drops after connecting to the database and before calling PDO::commit, quite good to know if you have a remote database server. So to answer your question, yes it can fail without throwing an exception, but its timing has to be very specific even more so if you have a local database."


来自 will a false returned PDO execute() the same as the exception it thrown? :

这是我遇到的唯一能够复制的特定场景(见上文)。

  1. "(Niksac) I have seen execute() returning false without throwing an exception which is kind of unexpected / bad behaviour in my opinion. This means that we basically have to do both - error and exception handling in parallel. In my case: if I prepared an insert query without any parameters and then executed with a parameter. Execute will not throw an exception but return false."


来自 Should I check the return value of an execute operation in pdo php :

  1. "(castis) $stmt->execute() can absolutely return false without throwing an exception."


我想我至少发现了另外一个可能的非特定提及(错误返回,无一异常(exception)),尽管我无法再次追踪它们。

在线查看 PDO 教程,其中大多数不会在使用异常模式时检查返回值。但我确实遇到了几个人推荐它。

我描述的案例不是我在日常使用中可能会搞砸的东西。或者如果我真的搞砸了,我应该立即找出答案。如果我曾经在查询中动态构建占位符或参数的数量,我会知道在这种情况下确保计数匹配和/或检查 false。

如果不是真的有必要,我只是不想检查每次使用执行、查询等的返回值。如果我提到的示例是唯一已知的情况,我会很放心地将大多数查询中的错误检查排除在外,这将允许我进行更多的方法链接:
$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();

我想我正在寻找的是更有经验的开发人员的一些保证,可以像我看到的那样绕过这个检查。要么,要么人们告诉我他们是如何绕过该检查而被烧毁的。

最佳答案

根据您使用的数据库,肯定有不同的陷阱。如果考虑可移植性,我不会依赖上面您似乎发现的某些可能是 MySQL 的特性。

例如,有这些:

  • PHP PDO Postgres versus Sqlite column type for count(*)
  • PHP Postgres PDO driver does not support prepared statement?
  • 关于异常模式下的 PHP PDO - 仍然需要检查执行函数(和其他函数)的返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42353280/

    相关文章:

    php - 如何使用 IN,FIND_IN_SET 比较逗号分隔字符串中的多个值?

    php - 如何在一个查询中编写 asc 和

    java - java中代码层的异常处理

    c# - "Access to the path ' a-guid.8Event ' is denied."启动时

    Php PDO Mysql 选定值下拉列表

    php - phpmailer 的问题

    php - 使用空格分割发布的文本并插入到mysql数据库中

    mysql - 从排名中排除得分为零的用户

    PHP - 正确显示 MySQL 的结果

    java.lang.IllegalArgumentException,我在游戏商店的崩溃报告中得到了这个异常,建议我如何解决这个问题......