处理PDO和语句异常

时间:2015-12-09 15:46:17

标签: php pdo

我们一直在查看我们的一些旧代码,我们发现了一些代码如下:

try
{
    $stmt = $db->prepare($query);
    $stmt->bindvalue(1, $id, PDO:ARAM_INT);
    $stmt->execute();
    $row = $stmt->fetchColumn();
}
catch(PDOException $e)
{
    echo "There was an issue with query: ";
    print_r($db->errorInfo());
}

乍一看,我们认为看起来很好(在Stack Exchange上甚至很多答案都将此作为示例代码)。然后我们查看了errorInfo函数的PHP文档,并声明:

  

PDO :: errorInfo()仅检索直接执行的操作的错误信息   数据库句柄。如果您通过创建PDOStatement对象   PDO:repare()或PDO :: query()并在语句上调用错误   handle,PDO :: errorInfo()不会反映语句中的错误   处理

如果我们理解正确,那意味着如果我们所做的任何语句操作出现任何问题,我们实际上不会打印出我们期望的错误代码"查询存在问题:"。这是对的吗?

鉴于此,我们开始寻找正确的方法来实现这一点,我们首先查看PDOException类文档,该文档表明我们可能会执行以下操作:

try
{
    $stmt = $db->prepare($query);
    $stmt->bindvalue(1, $id, PDO:ARAM_INT);
    $stmt->execute();
    $row = $stmt->fetchColumn();
}
catch(PDOException $e)
{
    echo "There was an issue with query: ";
    print_r($e->errorInfo());
}

我的问题是:

  1. 以上方式是这样做的正确方法吗?如果没有,那么正确的做法是什么?
  2. 使用$ db-> errorInfo()和$ db-> errorCode(或$ stmt-> errorInfo和$ stmt-> errorCode)可以获得更多有用的信息,超出了您从PDOException中看到的信息?
  3. 如果在这些详细调用中有任何更详细的可用和有用的信息,那么有没有办法通过检查PDOException来区分它是由PDO还是PDOStatement引发的?

1 个答案:

答案 0 :(得分:1)

$db->prepare或任何$stmt操作都可能抛出异常。你不知道错误是从哪里来的,所以你不应该猜。异常本身包含有关出错的所有信息,所以是的,咨询它,只有这是唯一合理的事情。

此外,对于数据库调用,try..catch通常是无意义的(除非您对此特定数据库操作失败时要做的事情有明确的计划)。在您的示例中,您只是输出错误并继续,就像没有发生任何事情一样。这不是理智的错误处理。如果出现严重错误,则明确存在中止和跳转的例外情况,这意味着您的代码实际应该catch异常的部分应该存在多个层次,并且无法访问$db或完全$stmt(因为它在不同的范围内)。也许你根本不应该捕获异常并让它终止你的整个脚本(再次,除非你预期会发生错误并且有一个明确的计划如何处理它以及如何将你的应用程序恢复到已知状态) 。因此,仅查看异常本身的信息是唯一明智的做法。

  

如果在这些详细调用中有任何更详细的可用和有用的东西,那么有没有办法通过检查PDOException来区分它是由PDO还是PDOStatement引发的?

这仅在再次,您有任何类型的恢复计划时才有用,并且该计划因错误发生的位置而异。首先,我对此表示怀疑,但如果情况确实如此,那么你可以这样做:

try {
    $stmt = $db->prepare($query);
} catch (PDOException $e) {
    // do something to save the day
}

try {
    $stmt->bindValue(...)
    ..
} catch (PDOException $e) {
    // save the day another way
}

换句话说,您将try..catch语句隔离到要区分的代码的较小部分。但是,真的......如果$db->prepare失败了,你打算做什么?无论如何,您都无法继续使用其余代码。与$stmt方法失败相比,您打算以不同方式做什么?作为一个原子单元,您无法查询数据库,句号。

PDOException::$code将为您提供更详细的SQLState错误代码,这可能会告诉您一些有用的信息(例如,唯一约束违规),这是偶尔使用的有用信息。但是在检查时,哪条特定线路引起错误是非常无关紧要的。