[php] 하나의 catch 블록에서 여러 예외 유형 잡기

나는 캐치로, 다음과 같은 기능을 얻을 수있는 청소기 방법을 싶습니다 AErrorBError한 블록에 :

try
{
    /* something */
}
catch( AError, BError $e )
{
    handler1( $e )
}
catch( Exception $e )
{
    handler2( $e )
}

이것을 할 수있는 방법이 있습니까? 아니면 따로 잡아야합니까?

AErrorBerror공유 기본 클래스를 가지고,하지만 난을 통해 가을에하고 싶은 것을 그들은 또한 다른 유형과 공유 handler2난 그냥 기본 클래스를 잡을 수 있습니다.



답변

최신 정보:

PHP 7.1부터 사용할 수 있습니다.

구문은 다음과 같습니다.

try
{
    // Some code...
}
catch(AError | BError $e)
{
    // Handle exceptions
}
catch(Exception $e)
{
    // Handle the general case
}

문서 : https://www.php.net/manual/en/language.exceptions.php#example-287

RFC : https://wiki.php.net/rfc/multiple-catch

커밋 : https://github.com/php/php-src/commit/0aed2cc2a440e7be17552cc669d71fdd24d1204a


7.1 이전의 PHP :

이러한 다른 답변의 말에도 불구하고, 당신은 잡을 수 AErrorBError같은 블록에 (당신이 예외를 정의하는 하나의 경우는 다소 쉽다). “중단”하려는 예외가 있다고해도 필요에 맞게 계층을 정의 할 수 있어야합니다.

abstract class MyExceptions extends Exception {}

abstract class LetterError extends MyExceptions {}

class AError extends LetterError {}

class BError extends LetterError {}

그때:

catch(LetterError $e){
    //voodoo
}

여기여기 에서 볼 수 있듯이 SPL기본 예외 조차도 활용할 수있는 계층 구조가 있습니다. 또한 PHP 매뉴얼에 명시된 바와 같이 :

예외가 발생하면 명령문 뒤의 코드가 실행되지 않고 PHP는 첫 번째 일치하는 catch 블록을 찾으려고 시도합니다.

이것은 또한 당신이 가질 수 있음을 의미합니다

class CError extends LetterError {}

당신이 다르게 처리해야하는 AErrorBError, 당신의 catch 문은 다음과 같이 할 수 있도록 :

catch(CError $e){
    //voodoo
}
catch(LetterError $e){
    //voodoo
}

동일한 수퍼 클래스에 합법적으로 속한 20 개 이상의 예외가 있고 그 중 5 개 (또는 큰 그룹)를 한 가지 방법으로 처리해야하고 나머지는 다른 방법으로 처리해야하는 경우에도 여전히이를 수행 할 수 있습니다.

interface Group1 {}

class AError extends LetterError implements Group1 {}

class BError extends LetterError implements Group1 {}

그리고:

catch (Group1 $e) {}

예외와 관련하여 OOP를 사용하는 것은 매우 강력합니다. 사용 일이 좋아 get_class하거나 instanceof해킹하고, 가능하면 피해야한다.

추가하고 싶은 또 다른 솔루션은 예외 처리 기능을 자체 메서드에 넣는 것입니다.

당신은 할 수 있었다

function handleExceptionMethod1(Exception $e)
{
    //voodoo
}

function handleExceptionMethod2(Exception $e)
{
    //voodoo
}

예외 클래스 계층 또는 인터페이스를 제어 할 수있는 방법이 전혀 없다고 가정하면 (그리고 거의 항상 방법 있을 것입니다) 다음을 수행 할 수 있습니다.

try
{
    stuff()
}
catch(ExceptionA $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionB $e)
{
    $this->handleExceptionMethod1($e);
}
catch(ExceptionC $e)
{
    $this->handleExceptionMethod1($e);
}
catch(Exception $e)
{
    $this->handleExceptionMethod2($e);
}

이러한 방식으로 예외 처리 메커니즘을 변경해야하는 경우 수정해야하는 유일한 단일 코드 위치가 있으며 일반적인 OOP 구성 내에서 작업하고 있습니다.


답변

PHP> = 7.1에서는 이것이 가능합니다. 아래 답변을 참조하십시오 .


예외를 수정할 수 있으면 이 답변을 사용하십시오 .

당신이 할 수 없다면, 당신은 모두를 잡아서 시도 Exception하고 어떤 예외가 발생했는지 확인할 수 instanceof있습니다.

try
{
    /* something */
}
catch( Exception $e )
{
    if ($e instanceof AError OR $e instanceof BError) {
       // It's either an A or B exception.
    } else {
        // Keep throwing it.
        throw $e;
    }
}

그러나 앞서 언급 한 답변에서 설명한대로 여러 catch 블록사용하는 것이 좋습니다 .

try
{
    /* something */
}
catch( AError $e )
{
   handler1( $e );
}
catch ( BError $b )
{
   handler2( $e );
}


답변

오는 PHP 7.1은 여러 유형을 잡을 수 있다는 것입니다.

그래서이 :

<?php
try {
    /* ... */
} catch (FirstException $ex) {
    $this->manageException($ex);
} catch (SecondException $ex) {
    $this->manageException($ex);
}
?>

<?php
try {

} catch (FirstException | SecondException $ex) {
    $this->manageException($ex);
}
?>

기능적으로 동일합니다.


답변

PHP 7.1부터

catch( AError | BError $e )
{
    handler1( $e )
}

흥미롭게도 다음을 수행 할 수 있습니다.

catch( AError | BError $e )
{
    handler1( $e )
} catch (CError $e){
    handler2($e);
} catch(Exception $e){
    handler3($e);
}

그리고 이전 버전의 PHP에서 :

catch(Exception $ex){
    if($ex instanceof AError){
        //handle a AError
    } elseif($ex instanceof BError){
        //handle a BError
    } else {
       throw $ex;//an unknown exception occured, throw it further
    }
}


답변

이 기사는 electrictoolbox.com/php-catch-multiple-exception-types 질문을 다룹니다 . 기사에서 직접 복사 한 게시물의 내용 :

예외 예

다음은이 예제의 목적으로 정의 된 예외 예입니다.

class FooException extends Exception
{
  public function __construct($message = null, $code = 0)
  {
    // do something
  }
}

class BarException extends Exception
{
  public function __construct($message = null, $code = 0)
  {
    // do something
  }
}

class BazException extends Exception
{
  public function __construct($message = null, $code = 0)
  {
    // do something
  }
}

여러 예외 처리

매우 간단합니다. 각 예외 유형마다 catch 블록이있을 수 있습니다.

try
{
  // some code that might trigger a Foo/Bar/Baz/Exception
}

catch(FooException $e)
{
  // we caught a foo exception
}

catch(BarException $e)
{
  // we caught a bar exception
}

catch(BazException $e)
{
  // we caught a baz exception
}

catch(Exception $e)
{
  // we caught a normal exception
  // or an exception that wasn't handled by any of the above
}

다른 catch 문에 의해 처리되지 않는 예외가 발생하면 catch (Exception $ e) 블록에 의해 처리됩니다. 반드시 마지막 일 필요는 없습니다.


답변

허용 된 답변의 확장으로 Exception 유형을 전환하여 원래 예제와 다소 유사한 패턴을 만들 수 있습니다.

try {

    // Try something

} catch (Exception $e) {

    switch (get_class($e)) {

        case 'AError':
        case 'BError':
            // Handle A or B
            break;

        case 'CError':
            // Handle C
            break;

        case default:
            // Rethrow the Exception
            throw $e;

    }

}


답변

예외 정의를 제어 할 수없는 경우 합리적인 대안이 있습니다. 예외가 발생했을 때 예외를 분류하려면 예외 변수의 이름을 사용하십시오. 그런 다음 try / catch 블록 다음에 예외 변수를 확인하십시오.

$ABError = null;
try {
    // something
} catch (AError $ABError) {  // let the exception fall through
} catch (BError $ABError) {  // let the exception fall through
} catch (Exception $e) {
    handler2($e);
}
if ($ABError) {
    handler1($ABError);
}

캐치 블록 구현 사이에 중복이 많은 경우이 다소 이상하게 보이는 접근 방법은 그만한 가치가 있습니다.