我想要一種更簡潔的方法來獲取以下功能,以在一個區塊中捕獲 AError
和 BError
:
try { /* something */ } catch( AError, BError $e ) { handler1( $e ) } catch( Exception $e ) { handler2( $e ) }
有什麼辦法可以做到這一點嗎?還是我必須單獨捕獲它們?
AError
和Berror
有一個共享基類,但它們也與我想落入handler2
的其他類型共享,所以我不能只捕獲基類。
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 ); }
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
不管這些其他答案怎麼說,您都可以在同一個區塊中捕獲 AError
和 BError
(如果您是定義異常的人,那就更容易了)。即使存在您希望「排除」的例外情況,您仍然應該能夠定義層次結構來滿足您的需求。
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 {}
您需要以不同於 AError
或 BError
的方式處理它,因此您的 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_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 的一般建構內工作。