如何在PHP中有效地使用try ... catch块

ILi*_*cos 75 php exception-handling try-catch

我一直在我的PHP代码中使用try..catch块,但我不确定我是否一直在正确使用它们.

例如,我的一些代码如下所示:

 try {
      $tableAresults = $dbHandler->doSomethingWithTableA();
      $tableBresults = $dbHandler->doSomethingElseWithTableB();
 } catch (Exception $e) {
      return $e;
 }
Run Code Online (Sandbox Code Playgroud)

所以我在同一个try/catch块中对多个数据库操作进行分组,因为如果在任何事务中发生任何异常,我将能够处理它.

我这样做是因为我认为它比以下更具可读性和效率:

 try {
       $tableAresults = $dbHandler->doSomethingWithTableA();
 } catch (Exception $e) {
       return $e;
 }
 try {
       $tableBresults = $dbHandler->doSomethingWithTableB();
 } catch (Exception $e) {
       return $e;
 }
Run Code Online (Sandbox Code Playgroud)

虽然,我不确定我所做的是一种好的做法,还是一种懒惰的方法来捕捉异常.

我的假设是,只有异常需要特殊处理时,它才应该有自己的try/catch块,否则将它们分组到同一个try/catch中应该没问题.

所以我的问题是:

每个数据库事务使用try/catch块有什么好处吗?或者我仍然可以在同一个try/catch块中对多个数据库事务进行分组而没有任何问题?

嵌套try/catch块可以吗?谢谢!

编辑

return语句主要仅用于演示目的,但我也使用了返回,catch()因为我正在向该方法发出AJAX请求,而Javascript期待一个JSON对象,然后如果发生异常,我返回一个空的JSON编码数组.我只是认为在我的示例中放置特定代码不会增加任何值.

Jon*_*Jon 89

重要的提示

下面的讨论假定我们正在讨论如上例所示的代码结构:无论选择哪种替代方案,异常都会导致该方法在逻辑上停止执行它在中间的任何操作.


只要你打算做同样的事情,无论try块中的哪个语句抛出异常,那么使用单个try/ 当然更好catch.例如:

function createCar()
{
    try {
      install_engine();
      install_brakes();
    } catch (Exception $e) {
        die("I could not create a car");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您可以并且打算以特定于其确切原因的方式处理故障,则多个try/ catch块是有用的.

function makeCocktail()
{
    try {
        pour_ingredients();
        stir();
    } catch (Exception $e) {
        die("I could not make you a cocktail");
    }

    try {
        put_decorative_umbrella();
    } catch (Exception $e) {
        echo "We 're out of umbrellas, but the drink itself is fine"
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 别忘了PHP5.5增加了对`finally`的支持 (4认同)

小智 21

为了后人的缘故,答案可能为时已晚.您应该检查变量的返回值并抛出异常.在这种情况下,您可以确保程序将从引发异常的位置跳转到catch块.在下面找到.

try{
   $tableAresults = $dbHandler->doSomethingWithTableA();
   if (!tableAresults) 
     throw new Exception('Problem with tableAresults');

  $tableBresults = $dbHandler->doSomethingElseWithTableB();
   if (!tableBresults) 
     throw new Exception('Problem with tableBresults');
} catch (Exception $e) {
    echo $e->getMessage();

}
Run Code Online (Sandbox Code Playgroud)


小智 9

单个try catch块更具可读性.如果它的重要标识出一种错误,我建议您自定义您的例外.

try {
  $tableAresults = $dbHandler->doSomethingWithTableA();
  $tableBresults = $dbHandler->doSomethingElseWithTableB();
} catch (TableAException $e){
  throw $e;
} catch (Exception $e) {
  throw $e;
}
Run Code Online (Sandbox Code Playgroud)


ark*_*cha 8

没有理由不使用单个块进行多个操作,因为任何抛出的异常都会阻止在失败的操作之后执行进一步的操作.至少只要你可以从捕获的异常中得出结论哪个操作失败了.只要没有处理某些操作就可以了.

但是我会说返回异常只会有限.函数的返回值应该是某个操作的预期结果,而不是异常.如果你需要对调用范围中的异常作出反应,那么要么不在函数内部捕获异常,而是在调用范围内,或者在完成一些调试日志记录之后重新抛出异常以便稍后处理.


Ian*_*ney 6

抛出异常时,立即停止执行并继续执行该catch{}块.这意味着,如果将数据库调用放在同一个try{}块中并$tableAresults = $dbHandler->doSomethingWithTableA();抛出异常,$tableBresults = $dbHandler->doSomethingElseWithTableB();则不会发生.使用第二个选项时,$tableBresults = $dbHandler->doSomethingElseWithTableB();仍然会发生,因为它在catch{}块之后,执行已恢复.

每种情况都没有理想的选择; 如果您希望第二个操作继续,则必须使用两个块.如果没有发生第二次操作是可接受的(或者是可取的),那么你应该只使用一次.