PHP에서 try… catch 블록을 효율적으로 사용하는 방법


78

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 개체를 예상하기 때문에 return in도 사용 하고 있습니다. 예외가 발생하면 빈 JSON 인코딩 배열을 반환합니다. . 내 예제에 특정 코드를 넣는 데 어떤 가치도 추가하지 않을 것이라고 생각했습니다.


저도 같은 답을 가지고 있습니다. 때에 따라 다르지! DB 트랜잭션은 상호 의존적 FOREIGN KEYS입니까? 테이블 B의 트랜잭션이 테이블 A의 트랜잭션에 의존합니까? 그것은 당신이 그들을 그룹화 할 수 있는지 여부를 결정하기 위해 스스로에게 물어봐야 할 것입니다.
CodeAngry 2013

예, 테이블 B의 트랜잭션은 테이블 A의 트랜잭션에 의존합니다. 따라서 transactionA가 실패하면 transactionB는 실행되지 않아야합니다. 실행할 수 있지만 어쨌든 빈 결과 집합을 반환합니다.
ILikeTacos 2013

6
그런 다음 그룹화하십시오! 하지만 무엇을 왜하고 있는지 이해해야합니다. 이렇게 생각해보세요 ... 일단 던지면 다음 코드 줄이 실행되어야합니까? 그렇지 않으면 try{}블록에 넣으십시오 . 내가하는 일은 ... catch(){}끝 후에도 계속 됩니다.
CodeAngry 2013

답변:


90

중요 사항

다음 토론에서는 위의 예에서와 같이 구조화 된 코드에 대해 이야기하고 있다고 가정합니다. 어떤 대안을 선택하든 예외로 인해 메서드가 중간에 있던 작업을 논리적으로 중지하게됩니다.


try블록의 어떤 문 이 예외를 throw 하더라도 동일한 작업을 수행하려는 한, 단일 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"
    }
}

4
에 대한 그 PHP5.5 추가 지원 잊지 마세요finally
마이크 매킨토시

21

후손을 위해 대답은 너무 늦을 수 있습니다. 변수의 반환 값을 확인하고 예외를 throw해야합니다. 이 경우 프로그램은 예외가 발생한 위치에서 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();

}

9

단일 try catch 블록이 더 읽기 쉽습니다. 중요한 오류 유형을 식별하는 경우 예외를 사용자 지정하는 것이 좋습니다.

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

7

예외가 발생하면 실패한 작업 이후에 추가 작업이 실행되지 않기 때문에 여러 작업에 단일 블록을 사용할 이유가 없습니다. 최소한 포착 된 예외에서 실패한 작업을 결론을 내릴 수있는 한. 일부 작업이 처리 되지 않으면 괜찮습니다 .

그러나 예외를 반환하는 것은 제한된 의미 일 뿐이라고 말하고 싶습니다. 함수의 반환 값은 예외가 아닌 일부 작업의 예상 결과 여야합니다. 호출 범위의 예외에 반응해야하는 경우 함수 내부에서 예외를 포착하지 말고 호출 범위에서 예외를 포착하거나 디버그 로깅 등을 수행 한 후 나중에 처리 할 수 ​​있도록 예외를 다시 던지십시오.


6

예외가 발생하면 실행이 즉시 중지되고 catch{}블록 에서 계속됩니다 . 즉, 동일한 try{}블록 에 데이터베이스 호출을 배치하고 $tableAresults = $dbHandler->doSomethingWithTableA();예외 $tableBresults = $dbHandler->doSomethingElseWithTableB();가 발생하면 발생하지 않습니다. 두 번째 옵션을 사용 하면 실행이 다시 시작될 때 블록 $tableBresults = $dbHandler->doSomethingElseWithTableB();이후이므로 계속 발생합니다 catch{}.

모든 상황에 이상적인 옵션은 없습니다. 두 번째 작업을 계속하려면 두 블록을 사용해야합니다. 두 번째 작업이 발생하지 않는 것이 허용 (또는 바람직한 경우)이면 하나만 사용해야합니다.


1

단일 try catch 블록에서 모든 작업을 수행 할 수 있습니다. 가장 좋은 방법은 특정 오류에 대한 자체 메시지와 함께 표시되도록하려면 다른 catch 블록에서 오류를 포착하는 것입니다.


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

0

아래와 같이 하나의 try catch 블록으로 여러 줄의 실행을 작성하는 데 문제가 없습니다.

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

install_engine또는 install_break함수 에서 실행이 발생하는 순간 컨트롤은 함수를 잡기 위해 전달됩니다. 한 가지 더 권장 사항은 예외를 적절하게 먹는 것입니다. 즉, 작성하는 대신 die('Message')항상 예외 프로세스를 올바르게 수행하는 것이 좋습니다. die()오류 처리에서는 함수 를 사용하는 것을 생각할 수 있지만 예외 처리에서는 사용할 수 없습니다.

다중 try catch 블록을 사용해야하는 경우 다른 코드 블록 예외가 다른 유형의 예외를 표시하도록하거나 아래와 같이 catch 블록에서 예외를 throw하려는 경우 다중 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')
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.