首頁  >  問答  >  主體

合併多個異常類型在一個catch區塊中

我想要一種更簡潔的方法來獲取以下功能,以在一個區塊中捕獲 AErrorBError

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

有什麼辦法可以做到這一點嗎?還是我必須單獨捕獲它們?

AErrorBerror 有一個共享基類,但它們也與我想落入handler2 的其他類型共享,所以我不能只捕獲基類。

P粉547420474P粉547420474388 天前597

全部回覆(2)我來回復

  • P粉777458787

    P粉7774587872023-10-15 15:07:15

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

    回覆
    0
  • P粉611456309

    P粉6114563092023-10-15 00:46:51

    更新:

    從 PHP 7.1 開始,此功能可用。

    語法是:

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

    文件:https://www.php.net/手冊/en/language.exceptions.php#example-334

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

    #提交:https://github.com/php/php-src/commit/ 0aed2cc2a440e7be17552cc669d71fdd24d1204a


    #對於 PHP 7.1 之前的版本:

    不管這些其他答案怎麼說,您都可以在同一個區塊中捕獲 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 手冊中所述:

    這意味著您也可以擁有

    class CError extends LetterError {}

    您需要以不同於 AErrorBError 的方式處理它,因此您的 catch 語句將如下所示:

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

    如果您遇到這樣的情況,其中有二十個或更多合法屬於同一超類的異常,並且您需要以一種方式處理其中五個(或任何大型組),而其餘的則以另一種方式處理,您仍然可以這樣做。

    interface Group1 {}
    
    class AError extends LetterError implements Group1 {}
    
    class BError extends LetterError implements Group1 {}

    然後:

    catch (Group1 $e) {}

    在處理異常時使用 OOP 非常強大。使用諸如 get_classinstanceof 之類的東西都是駭客行為,應該盡可能避免。

    我想添加的另一個解決方案是將異常處理功能放入自己的方法中。

    你可以有

    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 的一般建構內工作。

    回覆
    0
  • 取消回覆