Php 带有try-catch的PDO事务语法

Php 带有try-catch的PDO事务语法,php,pdo,transactions,Php,Pdo,Transactions,在使用PDO事务和try catch时,首选的语法是什么?为什么 $dbh->beginTransaction(); try { } catch (Exception $e) { } 或 try { $dbh->beginTransaction(); } catch (Exception $e) { } 这仅仅是因为在您尝试开始事务时可能会引发异常 请注意,您可以在初始try中放置另一个try-catch块。第二个块通常最有意义。由于您可能并不总是知道什么会导致事务失

在使用PDO事务和try catch时,首选的语法是什么?为什么

$dbh->beginTransaction();
try {

} catch (Exception $e) {


}

try {

$dbh->beginTransaction();

} catch (Exception $e) {

}
这仅仅是因为在您尝试开始事务时可能会引发异常


请注意,您可以在初始try中放置另一个try-catch块。

第二个块通常最有意义。由于您可能并不总是知道什么会导致事务失败,因此您希望catch中提供回滚(可能还有提交)逻辑,因此您希望将
beginTransaction()
放在try中

除了
try/catch
之外,请确保设置了错误模式属性:

$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
如果有什么问题,您应该捕获
pdoExecution
,因为您不应该以相同的方式处理所有异常

try {
    $dbh->beginTransaction();
    //do stuff
    $dbh->commit();
} catch (PDOException $e) {
    $dbh->rollBack();
    //...
    throw $e;
}
但如果仍要捕获其他异常,请添加更多捕获块:

try {
    ....
} catch (PDOException $e) {
  //handle pdo exception
}catch (Exception $ex) {
  //handle others differently 
}

现有的答案似乎表明,由于
$dbh->beginTransaction()
可能引发
PDOException
异常,因此它应该位于实际事务代码的同一
try
块中,但这意味着
rollBack()
代码本身将是错误的,因为它可能调用
rollBack()
而不存在事务,这也可能引发另一个
PDOException

正确的逻辑顺序是,在创建事务后,将要在一个事务中执行的代码放在一个catch块中。在继续之前,您还可以检查
beginTransaction()
的返回是否为
true
。您甚至可以在调用
rollback()
之前检查数据库会话是否在事务中

请记住,至少在理论上,您仍然可以从
beginTransaction()
rollBack()
获得异常,因此我将把它放在一个单独的函数中,并将调用包含在另一个
try catch
块中

您还可以对异常进行冒泡,以便捕获它并在一个位置记录所有异常。但请记住,有些异常可能是数据完整性错误,例如重复的密钥或无效的外键,这本身不是数据库错误,但很可能是代码中的错误


使用这种方法,这里要记住的主要事情是两个
try-catch
块的用途略有不同。内部查询纯粹是为了确保在一个事务中以原子方式执行和提交多个查询,如果发生了什么事情,它们将回滚。外部
try-catch
将检测错误情况并记录它,或者在数据库出现问题时执行任何操作

取决于您在
catch中执行的操作
try {
    ....
} catch (PDOException $e) {
  //handle pdo exception
}catch (Exception $ex) {
  //handle others differently 
}
if ($dbh->beginTransaction()) 
{
  try 
  {
    //your db code
    $dbh->commit();
  } 
  catch (Exception $ex) 
  {
    if ($dbh->inTransaction())
    {
       $dbh->rollBack();
    }        
  }
}