php 嵌套 try catch,关于异常处理:如何在PHP中有效地使用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()中使用RETURNS,因为我对该方法发出了Ajax请求,而javascript期望得到一个JSON对象,那么如果发生异常,我将返回一个空的JSON编码数组。我只是认为在我的示例中放入特定的代码不会增加任何值。

我有同样的答案。这要看情况!DB交易是否相互依赖,是否涉及FOREIGN KEYS?表B中的事务是否依赖于表A中的事务?这就是你需要问自己决定是否可以将他们分组的问题。

是的,表B中的事务依赖于表A中的事务。因此,如果Transactiona失败,则TransactionB不应运行。它可以运行,但无论如何它都会返回一个空的结果集。

那就分组吧!但要记住,你需要理解你在做什么,为什么要做。就这样想…一旦抛出,是否需要执行下一行代码?如果我不这样做,就把它们放在try{}块。我做的那些…在catch(){}结束后继续。

重要注意事项

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

只要您打算做同样的事情,不管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"

}

}

别忘了php5.5增加了对finally的支持

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

}

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

try {

$tableAresults = $dbHandler->doSomethingWithTableA();

$tableBresults = $dbHandler->doSomethingElseWithTableB();

} catch (TableAException $e){

throw $e;

} catch (Exception $e) {

throw $e;

}

没有理由不将单个块用于多个操作,因为任何引发的异常都将阻止在失败的操作之后执行进一步的操作。至少只要您能断定哪个操作因捕获的异常而失败。只要不处理某些操作就可以。

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

当抛出异常时,立即停止执行,并在catch{}块继续执行。这意味着,如果将数据库调用放在同一个try{}块中,而$tableAresults = $dbHandler->doSomethingWithTableA();抛出异常,则不会发生$tableBresults = $dbHandler->doSomethingElseWithTableB();。第二种选择是,当执行恢复时,$tableBresults = $dbHandler->doSomethingElseWithTableB();仍然会发生,因为它在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();

}

在一个try-catch块中,您可以做所有的事情,如果您希望不同的catch块中的错误显示为特定错误的消息,那么最佳实践是捕获它们。

用下面这样的一个try-catch块编写多行执行没有任何问题

try{

install_engine();

install_break();

}

catch(Exception $e){

show_exception($e->getMessage());

}

在install_engine或install_break函数中发生任何异常时,控制将被传递到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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值