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

时间:2013-07-09 13:33:41

标签: php exception-handling try-catch

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

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

 try {
      $tableAresults = $dbHandler->doSomethingWithTableA();
      $tableBresults = $dbHandler->doSomethingElseWithTableB();
 } catch (Exception $e) {
      return $e;
 }

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

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

 try {
       $tableAresults = $dbHandler->doSomethingWithTableA();
 } catch (Exception $e) {
       return $e;
 }
 try {
       $tableBresults = $dbHandler->doSomethingWithTableB();
 } catch (Exception $e) {
       return $e;
 }

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

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

所以我的问题是:

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

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

修改

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

8 个答案:

答案 0 :(得分:88)

重要提示

以下讨论假设我们正在讨论上面示例中构造的代码:无论选择哪种替代方案,异常都会导致该方法在逻辑上停止执行它在中间的任何内容。


只要您打算做同样的事情,无论try块中的哪个语句引发异常,那么使用单个try / catch肯定会更好。例如:

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

多个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"
    }
}

答案 1 :(得分:20)

为了后人,答案可能为时已晚。您应该检查变量的返回值并抛出异常。在这种情况下,您可以确保程序将从引发异常的位置跳转到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();

}

答案 2 :(得分:7)

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

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

答案 3 :(得分:7)

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

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

答案 4 :(得分:5)

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

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

答案 5 :(得分:0)

在单个try catch块中,你可以做所有的事情,最好的做法是在不同的catch块中捕获错误,如果你希望它们用自己的消息显示特定的错误。

答案 6 :(得分:0)

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();
}

答案 7 :(得分:-1)

使用单个try catch块编写多行执行没有任何问题,如下所示

try{
install_engine();
install_break();
}
catch(Exception $e){
show_exception($e->getMessage());
}

install_engineinstall_break函数中发生任何execption的那一刻,控件将被传递给catch函数。 还有一个建议是正确地吃掉你的例外。这意味着不要写die('Message'),而是始终建议正确进行异常处理。您可以考虑在错误处理中使用die()函数,但不要在异常处理中使用。

何时应该使用多个try catch块 如果您希望不同的代码块异常显示不同类型的异常,或者您尝试从catch块中抛出任何异常,您可以考虑多个try catch块,如下所示:

try{
    install_engine();
    install_break();
    }
    catch(Exception $e){
    show_exception($e->getMessage());
    }
try{
install_body();
paint_body();
install_interiour();
}
catch(Exception $e){
throw new exception('Body Makeover faield')
}

有关如何在不同情况下使用try catch块的更多详细信息,请参阅PHP Try Catch上的我的博客