我在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编码数组。我只是认为在我的例子中放置特定代码不会增加任何价值。
答案 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_engine
或install_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上的我的博客