【问题标题】:postgres php exception handlingpostgres php异常处理
【发布时间】:2016-03-07 01:42:20
【问题描述】:

我之前在 SO 上看到过这个问题,但似乎没有一个答案是完整的。所以请...

我有使用 PDO 和 PDOStatement 的代码。它最初是为无例外地工作而编写的,我正在将其转换为可以使用。

我的简单问题是:

  1. 有没有必要继续检查函数的返回值是否为FALSE(当这意味着“失败”),或者我可以简单地执行该方法并假设各种失败都会触发例外?我在一个答案中看到了一个示例,建议有人同时使用 try-catch 和测试 FALSE 的返回值 - 这实际上是必要的,这会产生一些非常丑陋的代码。
  2. 是否有正确的列表列出哪些方法可以抛出异常,哪些永远不能抛出异常?我看到答案说“如果您发现我们没有记录我们抛出的异常,请提出错误”,但这并不完全有帮助。我已经看到“手册页说明何时可以引发异常”的声明,但是 PDO::query 和 PDOStatement::execute 页面没有提及异常 - 这肯定不可能是真的......可以吗?本质上,我想知道是否准备、绑定 [事物]、获取 [全部]、执行以及其他一些可能或永远不会扔东西。

我不觉得我在问地球,如果需要我可以查看代码,但是关于这方面的手动文档肯定应该是坚如磐石的。

[编辑以添加示例]

我现在发现自己有这样的代码块——我想通过删除返回值的测试来简化它,但我无法说服自己它是正确的。其他块使用execute()等。

try {
  /* I do not know whether beginTransaction throws an exception when it would otherwise return FALSE.
   * If it does then checking the return value is spurious, and the code cam be simplified.
   */
  if (FALSE == $customerDb->beginTransaction()) {
    Log::add("Database begin transaction failed.",
              Log::ERROR);
  throw new Exception("Failed to begin a transaction.");
  }
} catch (PDOException $e) {
  /* The documentation does not mention the possibility of
   *  beginTransaction() throwing any exception,
   *  even when we have configured all the other functions to do so.
   */
  Log::add("Database begin transaction threw an exception: " . $e->getMessage(),
           Log::ERROR);
  throw new Exception("Begin transaction threw an exception.");
}

【问题讨论】:

    标签: php postgresql exception pdo


    【解决方案1】:

    共有三种错误处理策略,ERRMODE_SILENT(默认一种)、ERRMODE_WARNINGERRMODE_EXCEPTION。如果发生错误,只有最后一个使 PDO 抛出异常,所以除非你明确告诉 PDO 在异常模式下运行:

    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    

    它不会抛出任何异常,除了PDO:__construct(),它会在连接失败时抛出异常,无论PDO::ATTR_ERRMODE 的值如何。

    来自文档:

    PDO::__construct() 将始终抛出 PDOException 如果连接 无论当前设置了哪个PDO::ATTR_ERRMODE,都会失败。未捕获 异常是致命的。

    我建议您阅读the documentation - PDO 如何处理错误非常清楚。

    更新

    在您的代码示例中,当您将 catch 块异常键入 PDO_Exception 并且您正在抛出 Exception - 这是较低的异常类型级别时,该异常将永远不会被捕获。如果您想捕获所有异常类型,请将您的 catch 参数转换为 Exception - 目前您的 catch 块仅捕获 PDOException

    话虽如此,让我们专注于您对异常的困惑。在ERRMODE_SILENTERRMODE_WARNING没有任何神秘异常被抛出,除了来自 PDO 控制器的异常 - 已记录在案。另有说明的人可能在他们并不真正了解/控制的 PDO 环境中工作——比如一个使用 PDO 但抛出自己的查询异常的框架,或者在特定情况下更改ATTR_ERRMODE。我建议你少关注 docs 下的讨论(因为有时候里面可能有一些有趣的东西,大多数时候是迷糊的人的 cmets),而更多地关注 docs 本身。

    让我们弄清楚 PDO 中的错误会发生什么。

    1. 出现错误。如果它发生在 PDO 控制器中,则会抛出异常并忽略所有后续步骤。

    2. 错误将根据the SQL-92 standard 进行标准化(请参阅此链接了解所有存在的返回代码)。来自文档:

      PDO 标准化使用 SQL-92 SQLSTATE 错误代码字符串;各个 PDO 驱动程序负责将其本机代码映射到适当的 SQLSTATE 代码。

    3. PDO 检查ATTR_ERMODE 属性以了解它应如何处理此错误。

      1. ERRMODE_SILENT(默认模式)

        不会报告错误,因此您需要检查 false 的 PDO 函数的返回,并根据对象检查 PDO::errorCode()PDO::errorInfo()PDOStatement::errorCode()PDOStatement::errorInfo()您用于获取错误详细信息。

      2. ERRMODE_WARNING

        ERRMODE_SILENT 相同,但会抛出E_WARNING PHP 错误。可能对开发有用,但您仍然需要检查false 的函数返回。

      3. ERRMODE_EXCEPTION

        PDO_Exception 将被抛出。 不需要检查false的函数返回,因为当抛出异常时,将跳过下一行,PHP将进入catch块,或者如果没有任何catch阻止它会抛出一个PHP错误。因此,在ERRMODE_EXCEPTION 中运行时,您建议的实现是多余的。

    所以是的,文档没有说 x 函数抛出异常,因为它完全是多余的。错误处理页面解释了您需要了解的所有内容。

    如果你还是不服气,建议你自己试试看:玩ATTR_ERRMODE和各种PDO函数,自己看看。

    【讨论】:

    • 变种。谢谢你的回复,我都知道,但似乎没有帮助。这似乎与我的两个问题几乎没有关系。我已经阅读了“文档”,如果他们涵盖了它,我就不会问这个问题。文档是 UNCLEAR,即 2 个示例(查询和执行),其中肯定会引发异常,但我在文档中看不到任何内容。 “相当清楚”不是“实际上清楚”。如果您点击您的链接,您会看到 Praveen Raj 的评论,这几乎与我在这里提出的询问/投诉相呼应!之前在 SO 上被问过很多次,但没有回答。
    • 这里我还是没明白你不明白的地方。如果您不处于异常模式,PDO::query 不会抛出任何异常,与 PDO::statement:execute 相同。关于 Praveen 的评论,他只是说如果你将 ATTR_ERRMODE 设置为 ERRMODE_EXCEPTION,它也将适用于 PDOStatement 对象。他引用的所有方法都清楚地记录在案,例如prepare:“PDO::prepare() 返回 FALSE 或发出 PDOException(取决于错误处理)。”。我看不出还有什么比这更清楚的。
    • 你误读了文档,当他们说“如果你发现我们没有记录我们抛出的异常,请提出错误”,这是关于 exception 本身的文档,不是函数引发异常的事实 - 这是有文档的。
    • 好的。我们显然没有看到同样的事情。考虑php.net/manual/en/pdostatement.execute.php 我看到有人在讨论输入参数时提到了一个错误。我没有看到异常的文档。我没有看到任何声明(启用时)总是会抛出异常而不是返回“FALSE”,因此如果启用异常,则永远不需要测试 FALSE 的返回值。该讨论可能存在于其他地方,但我没有找到它。
    • 我附加了一个代码示例,显示我对这个问题的困惑。
    猜你喜欢
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-25
    • 2016-02-29
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多