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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17549584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 16:05:41  来源:igfitidea点击:

How to efficiently use try...catch blocks in PHP

phpexception-handlingtry-catch

提问by ILikeTacos

I have been using try..catch blocks in my PHP code, but I'm not sure if I've been using them correctly.

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

For example, some of my code looks like:

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

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

So I'm grouping multiple database operations in the same try/catch block because if any exception occurs in any of the transaction, I will be able to handle it.

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

I'm doing it that way because I think that it's more readable and efficient than:

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

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

Although, I'm not sure if what I'm doing is a good practice or just a lazy way to catch exceptions.

虽然,我不确定我在做什么是一种好的做法,还是只是一种捕获异常的懒惰方法。

My assumption is that only if an exception requires special handling, it should have its own try/catch block, otherwise grouping them in the same try/catch should be ok.

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

So my question(s) are:

所以我的问题是:

Is there any advantage of using try/catch blocks per database transaction? or can I still group multiple database transactions in the same try/catch block with no problem at all?

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

Is it ok to nest try/catch blocks? Thanks!

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

EDIT

编辑

The return statement was primarily for demonstration purposes only, but I'm also using returns in catch()because I'm making an AJAX request to that method, and Javascript is expecting a JSON object, then if an exception occurs I return an empty JSON encoded array. I just thought that It wouldn't add any value to put specific code in my example.

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

回答by Jon

Important note

重要的提示

The following discussion assumes that we are talking about code structured as in the example above: no matter which alternative is chosen, an exception will cause the method to logically stop doing whatever it was in the middle of.

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



As long as you intend to do the same thing no matter which statement in the tryblock throws an exception, then it's certainly better to use a single try/catch. For example:

只要你打算做同样的事情,不管try块中的哪个语句抛出异常,那么使用单个try/肯定更好catch。例如:

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

Multiple try/catchblocks are useful if you can and intend to handle the failure in a manner specific to what exactly caused it.

如果您可以并打算以特定于确切原因的方式处理失败,则多个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"
    }
}

回答by kodepet

For posterity sake,the answer maybe too late.You should check for the return value of the variable and throw an exception. In that case you are assured that the program will jump from where the exception is being raised to the catch block. Find below.

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

}

回答by zongo

It's more readable a single try catch block. If its important identify a kind of error I recommend customize your Exceptions.

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

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

回答by arkascha

There is no reason against using a single block for multiple operations, since any thrown exception will prevent the execution of further operations after the failed one. At least as long as you can conclude which operation failed from the exception caught. That is as long as it is fine if some operations are notprocessed.

没有理由反对将单个块用于多个操作,因为任何抛出的异常都会阻止在失败的操作之后执行进一步的操作。至少只要您可以从捕获的异常中推断出哪个操作失败了。只要处理某些操作就可以了。

However I'd say that returning the exception makes only limited sense. A return value of a function should be the expected result of some action, not the exception. If you need to react on the exception in the calling scope then either do not catch the exception here inside your function, but in the calling scope or re-throw the exception for later processing after having done some debug logging and the like.

但是我想说返回异常的意义有限。函数的返回值应该是某个动作的预期结果,而不是异常。如果您需要对调用范围内的异常做出反应,那么要么不要在函数内部捕获异常,而是在调用范围内捕获异常,要么在完成一些调试日志记录等之后重新抛出异常以供以后处理。

回答by IanPudney

When an exception is thrown, execution is immediately halted and continues at the catch{}block. This means that, if you place the database calls in the same try{}block and $tableAresults = $dbHandler->doSomethingWithTableA();throws an exception, $tableBresults = $dbHandler->doSomethingElseWithTableB();will not occur. With your second option, $tableBresults = $dbHandler->doSomethingElseWithTableB();will still occur since it is after the catch{}block, when execution has resumed.

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

There is no ideal option for every situation; if you want the second operation to continue regardless, then you must use two blocks. If it is acceptable (or desirable) to have the second operation not occur, then you should use only one.

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

回答by Amar Agrawal

in a single try catch block you can do all the thing the best practice is to catch the error in different catch block if you want them to show with their own message for particular errors.

在单个 try catch 块中,您可以执行所有操作,最佳实践是在不同的 catch 块中捕获错误,如果您希望它们显示自己的特定错误消息。

回答by nitin kumar maurya

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

回答by Ankur Kumar Singh

There is no any problem to write multiple lines of execution withing a single try catch block like below

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

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

The moment any execption occure either in install_engineor install_breakfunction the control will be passed to catch function. One more recommendation is to eat your exception properly. Which means instead of writing die('Message')it is always advisable to have exception process properly. You may think of using die()function in error handling but not in exception handling.

install_engineinstall_break函数中发生任何 execption 的那一刻,控制将传递给 catch 函数。另一项建议是正确食用您的例外情况。这意味着不要写die('Message')它总是建议正确地进行异常处理。您可能会想到die()在错误处理中使用函数,而不是在异常处理中。

When you should use multiple try catch block You can think about multiple try catch block if you want the different code block exception to display different type of exception or you are trying to throw any exception from your catch block like below:

何时应该使用多个 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')
}

For more detail about how you can use try catch block in different cases you may refer to my blog on PHP Try Catch

有关如何在不同情况下使用 try catch 块的更多详细信息,您可以参考我关于PHP Try Catch 的博客