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

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

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

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

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

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

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

虽然,我不确定我所做的是一个好的做法,或只是一个懒惰的方式来捕捉exception。

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

所以我的问题是:

每个数据库事务使用try / catch块是否有优势? 或者我仍然可以在同一个try / catch块中组合多个数据库事务,而没有任何问题呢?

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

编辑

返回语句主要是为了演示的目的,但我也在catch()使用返回,因为我正在向该方法发出AJAX请求,而Javascript期待JSON对象,那么如果发生exception,我将返回一个空JSON编码数组。 我只是认为它不会增加任何价值,把具体的代码在我的例子。

重要的提示

下面的讨论假定我们正在讨论上面例子中的代码结构:无论select哪一种替代方法,一个例外都会导致该方法在逻辑上停止在中间的任何事情。


只要你打算做同样的事情,不pipetry语句中哪个语句抛出一个exception,那么最好使用一个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" } } 

为了后代的缘故,答案可能为时已晚。您应该检查variables的返回值并抛出exception。 在这种情况下,您可以放心,程序将从exception提出的地方跳到catch块。 在下面find。

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

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

对于任何情况都没有理想的select; 如果你想不pipe第二个操作继续,那么你必须使用两个块。 如果第二个操作没有发生是可以接受的(或可取的),那么你应该只使用一个。

没有理由反对使用单个块进行多个操作,因为任何抛出的exception都将阻止在失败之后执行进一步的操作。 至less只要你能断定哪一个操作失败了,就会发现exception。 只要一些操作没有被处理,就可以。

但是我会说,返回exception只是有限的意义。 函数的返回值应该是某个操作的预期结果,而不是例外。 如果您需要对调用作用域中的exception作出反应,那么要么在函数内部捕获exception,而要在调用作用域中捕获exception,或者在完成一些debugging日志logging等之后重新抛出exception以供以后处理。

这是一个单一的try catch块更可读。 如果它的重要标识一种错误,我build议自定义您的例外。

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

在一个try catch块中,你可以做所有的事情,最好的做法是捕捉不同的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{ install_engine(); install_break(); } catch(Exception $e){ show_exception($e->getMessage()); } 

install_engineinstall_break函数中发生任何错误时,控制权将被传递给catch函数。 还有一个build议是正确地吃你的例外。 这意味着不要写die('Message') ,总是build议exception处理正确。 您可能会考虑在error handling中使用die()函数,而不是在exception处理中使用。

当你应该使用多个try catch块的时候你可以考虑多个try catch块,如果你想让不同的代码块exception显示不同types的exception,或者试图从catch块中抛出任何exception,如下所示:

 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 Try Catch上的博客