1つのキャッチブロックで複数の例外タイプをキャッチします -- php フィールド と exception-handling フィールド 関連 問題

Catching multiple exception types in one catch block












270
vote

問題

日本語

次の機能を取得するためのクリーナーな方法で、 AError および<コード> BError

をキャッチしたいです。 <事前> <コード> try { /* something */ } catch( AError, BError $e ) { handler1( $e ) } catch( Exception $e ) { handler2( $e ) }

これを行う方法はありますか?それとも私はそれらを別々に捕まえる必要がありますか?

<コード> AError と<コード> Berror には共有基本クラスがありますが、 handler2 、ベースクラスを捕まえることはできません。

英語

I'd like a cleaner way to obtain the following functionality, to catch AError and BError in one block:

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

Is there any way to do this? Or do I have to catch them separately?

AError and Berror have a shared base class, but they also share it with other types that I'd like to fall through to handler2, so I can't just catch the base class.

</div
     
     
     

回答リスト

404
 
vote
vote
ベストアンサー
 

更新:

PHP 7.1以降、これは利用可能です。

構文は次のとおりです。

<事前> <コード> try { // Some code... } catch(AError | BError $e) { // Handle exceptions } catch(Exception $e) { // Handle the general case }

docs: https://www.php.net/手動/ en / language.exceptions.php#例-294

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

commit: https://github.com/php/php-src/commit/ 0AED2CC2A440E7BE17552CC669D71FDD24D1204A


PHPの場合7.1:

これらの他の回答が言うにもかかわらず、 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 manual

に記載されているように

例外がスローされると、ステートメントの後のコードは含まれません。 実行され、 PHPは最初の一致するキャッチブロックを見つけようとします。

これはあなたが

を持つことができることを意味します <事前> <コード> class CError extends LetterError {}

AError または<コード> BError とは異なる方法を扱う必要があるため、キャッチステートメントは次のようになります。

<事前> <コード> catch(CError $e){ //voodoo } catch(LetterError $e){ //voodoo }

正当なスーパークラスの下に属していた20以上の例外がある場合は、一方向に5つ(またはどんな大きなISHグループ)を扱う必要がある場合は、もう1つの方法で扱う必要があります。これを行います。

<事前> <コード> AError0

、次に

<事前> <コード> AError1

例外になるとOOPを使うことは非常に強力です。 <コード> AError2 OR AError3 のようなものを使用すると、可能であれば避けるべきです。

もう1つの解決策を追加したいと思います。

あなたは

を持つことができます <事前> <コード> AError4

例外クラスの階層やインタフェースを制御することができないと仮定することで(ほとんど常にになることがあります)、次のことができます。

<事前> <コード> AError5

このようにしても、例外処理メカニズムが変更が必要な場合は、変更する必要がある単一のコードの場所があり、OOPの一般的な構成要素内で作業しています。

 

Update:

As of PHP 7.1, this is available.

The syntax is:

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

Docs: https://www.php.net/manual/en/language.exceptions.php#example-294

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

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


For PHP before 7.1:

Despite what these other answers say, you can catch AError and BError in the same block (it is somewhat easier if you are the one defining the exceptions). Even given that there are exceptions you want to "fall through", you should still be able to define a hierarchy to match your needs.

abstract class MyExceptions extends Exception {}  abstract class LetterError extends MyExceptions {}  class AError extends LetterError {}  class BError extends LetterError {} 

Then:

catch(LetterError $e){     //voodoo } 

As you can see here and here, even the SPL default exceptions have a hierarchy you can leverage. Additionally, as stated in the PHP Manual:

When an exception is thrown, code following the statement will not be executed, and PHP will attempt to find the first matching catch block.

This means you could also have

class CError extends LetterError {} 

which you need to handle differently than AError or BError, so your catch statement would look like this:

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

If you had the case where there were twenty or more exceptions that legitimately belonged under the same superclass, and you needed to handle five (or whatever large-ish group) of them one way and the rest the other, you can STILL do this.

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

And then:

catch (Group1 $e) {} 

Using OOP when it comes to exceptions is very powerful. Using things like get_class or instanceof are hacks, and should be avoided if possible.

Another solution I would like to add is putting the exception handling functionality in its own method.

You could have

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

Assuming there is absolutely no way you can control exception class hierarchies or interfaces (and there almost always will be a way), you can do the following:

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

In this way, you are still have a only single code location you have to modify if your exception handling mechanism needs to change, and you are working within the general constructs of OOP.

</div
 
 
         
         
232
 
vote

PHP&GT; = 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; } }

しかしそれはおそらく前述の答えで説明されているように複数のキャッチブロックを使用することになるでしょう。 。

<事前> <コード> try { /* something */ } catch( AError $e ) { handler1( $e ); } catch ( BError $b ) { handler2( $e ); }
 

In PHP >= 7.1 this is possible. See this answer.


If you can modify the exceptions, use this answer.

If you can't, you could try catching all with Exception and then check which exception was thrown with 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;     } } 

But it would probably be better to use multiple catch blocks as described in aforementioned answer.

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

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

は機能的に同等です。

 

Coming in PHP 7.1 is the ability to catch multiple types.

So that this:

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

and

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

are functionally equivalent.

</div
 
 
47
 
vote

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 } }
 

As of PHP 7.1,

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

interestingly, you can also:

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

and in earlier versions of 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     } } 
</div
 
 
25
 
vote

この記事では、質問 ElectrictoolBox.com/php-catch-multiple-exception-types( a>。記事から直接コピーされた投稿の内容:

例外例

この例の目的で定義されている例外例:

<事前> <コード> 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 } }

複数の例外を処理する

それは非常に単純です - 投げられる可能性のある例外タイプごとにキャッチブロックがある可能性があります。

<事前> <コード> instanceof0

他のキャッチステートメントのいずれかによって処理されていない例外がスローされている場合は、キャッチ(例外$ E)ブロックによって処理されます。必ずしも最後のものである必要はありません。

 

This article covers the question electrictoolbox.com/php-catch-multiple-exception-types. Content of the post copied directly from the article:

Example exceptions

Here's some example exceptions that have been defined for the purposes of this example:

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   } } 

Handling multiple exceptions

It's very simple - there can be a catch block for each exception type that can be thrown:

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 } 

If an exception is thrown that is not handled by any of the other catch statements it will be handled by the catch(Exception $e) block. It does not necessarily have to be the last one.

</div
 
 
     
     
21
 
vote

承認された回答の拡張として、元の例のような模様のようなパターンの種類を切り替えることができます。

<事前> <コード> instanceof1
 

As an extension to the accepted answer, you could switch the type of Exception resulting in a pattern that is somewhat like the original example:

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;      }  } 
</div
 
 
 
 
5
 
vote

例外の定義を制御していない場合は、これが合理的な代替手段です。例外変数の名前を使用して、キャッチされたときに例外を分類します。その後、try / catchブロックの後に例外変数を確認してください。

<事前> <コード> instanceof2

これは、キャッチブロック実装の間にたくさんの重複がある場合にのみ価値があるのはおそらくそれだけの価値があります。

 

Here's a reasonable alternative if you don't have control over defining the exceptions. Use the name of the exception variable to categorize the exceptions when they are caught. Then check for the exception variable after the try/catch block.

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

This somewhat odd looking approach is probably only worth it if there is a lot of duplication between catch block implementations.

</div
 
 
3
 
vote

脱落以外にも、 goto を使用して踏み出すことも可能です。 あなたが世界を燃やすのを見たいのなら、とても便利です。

<事前> <コード> instanceof3

3v4l.org

 

Besides fall-through, it's also possible to step over by using goto. It's very useful if you want to see the world burn.

<?php  class A_Error extends Exception {} class B_Error extends Exception {} class C_Error extends Exception {}  try {     throw new A_Error(); }  catch (A_Error $e) { goto abc; } catch (B_Error $e) { goto abc; } catch (C_Error $e) { abc:     var_dump(get_class($e));     echo "Gotta Catch 'Em All "; } 

3v4l.org

</div
 
 
3
 
vote

HMM、7.1より低いPHPバージョンには多くの解決策が書き込まれています。

これは、すべての例外をキャッチしたくない人のための他の単純なものであり、共通のインターフェイスを作成できない:

<事前> <コード> instanceof4
 

Hmm, there are many solution written for php version lower than 7.1.

Here is an other simple one for those who doesn't want catch all exception and can't make common interfaces:

<?php $ex = NULL try {     /* ... */ } catch (FirstException $ex) {     // just do nothing here } catch (SecondException $ex) {     // just do nothing here } if ($ex !== NULL) {     // handle those exceptions here! } ?> 
</div
 
 
1
 
vote

別のオプションここに記載されていない他のオプションは、例外の code 属性を使用することです。

<事前> <コード> try { if (1 === $foo) { throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1); } if (2 === $bar) { throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2); } } catch (Exception $e) { switch ($e->getCode()) { case 1: // Special handling for case 1 break; case 2: // Special handling for case 2 break; default: // Special handling for all other cases } }
 

Another option not listed here is to use the code attribute of an exception, so you can do something like this:

try {      if (1 === $foo) {           throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1);     }      if (2 === $bar) {         throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2);     } } catch (Exception $e) {      switch ($e->getCode()) {          case 1:             // Special handling for case 1             break;          case 2:             // Special handling for case 2             break;          default:              // Special handling for all other cases     } } 
</div
 
 
     
     
1
 
vote

<コード> set_exception_handler を使用することです。

警告! PHP 7では、致命的な誤差のために故障の死の画面を入手するかもしれません。たとえば、オブジェクト以外のメソッドを呼び出すと、通常は Fatal error: Call to a member function your_method() on null が取得され、エラー報告がオンの場合はこれが表示される予定です。

上記のエラーは catch(Exception $e) で捉えられません。 上記のエラーは、 9988777665 によって設定されたカスタムエラーハンドラをトリガーしません。

catch(Error $e){ } を使用してPHP7のエラーをキャッチする必要があります。 。 これは助けることができます:

<事前> <コード> class ErrorHandler{ public static function excep_handler($e) { print_r($e); } } set_exception_handler(array('ErrorHandler','excep_handler'));
 

A great way is to use set_exception_handler.

Warning!!! with PHP 7, you might get a white screen of death for fatal errors. For example, if you call a method on a non-object you would normally get Fatal error: Call to a member function your_method() on null and you would expect to see this if error reporting is on.

The above error will NOT be caught with catch(Exception $e). The above error will NOT trigger any custom error handler set by set_error_handler.

You must use catch(Error $e){ } to catch errors in PHP7. . This could help:

class ErrorHandler{     public static function excep_handler($e)     {         print_r($e);     } } set_exception_handler(array('ErrorHandler','excep_handler')); 
</div
 
 
 
 
0
 
vote

PHP 8.0以降では、エラーの内容を出力する必要がない場合は、クリーナーな方法でも使用できます(変数 $e )。ただし、デフォルトの 998877699 try { if (1 === $foo) { throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1); } if (2 === $bar) { throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2); } } catch (Exception $e) { switch ($e->getCode()) { case 1: // Special handling for case 1 break; case 2: // Special handling for case 2 break; default: // Special handling for all other cases } } 0 に置き換える必要があります。

<事前> <コード> try { if (1 === $foo) { throw new Exception(sprintf('Invalid foo: %s', serialize($foo)), 1); } if (2 === $bar) { throw new Exception(sprintf('Invalid bar: %s', serialize($foo)), 2); } } catch (Exception $e) { switch ($e->getCode()) { case 1: // Special handling for case 1 break; case 2: // Special handling for case 2 break; default: // Special handling for all other cases } } 1
 

As of PHP 8.0 you can use even cleaner way to catch your exceptions when you don't need to output the content of the error (from variable $e). However you must replace default Exception with Throwable.

try {     /* something */ } catch (AError | BError) {     handler1() } catch (Throwable) {     handler2() } 
</div
 
 
     
     

関連する質問

3  G ++の問題:例外はキャッチされません  ( G problem exception not caught ) 
状況は、C ++でもPythonに折り返されたC ++で書き込まれた動的ライブラリーが、C ++(SIPによって生成されるように生成された)で書かれていることです。最初の動的ライブラリは、 do_raise の関数 do_raise を定義します。これは、 s...

0  Pythonにおける関数の例外処理  ( Exception handling of a function in python ) 
関数が確実にあるとします: <事前> <コード> def test(): print 'hi' 引数を与えるたびにTypeErrorを取得します。 今、DEFステートメントを試してみたい。どうやってこれを行いますか? ...

59  Pythonで例外が発生したときにプログラムを停止するにはどうすればよいですか。  ( How do i stop a program when an exception is raised in python ) 
Pythonで例外が発生したときにプログラムを停止する必要があります。 これを実装するにはどうすればよいですか? ...

2  1つのキャッチブロックで2つの異なる例外に行動する  ( Acting on two different exceptions in one catch block ) 
.NETの2つの異なる例外をキャッチして1つのキャッチブロックに処理する方法はありますか? 私はのようなものを考えています <事前> <コード> try {} catch(OverflowException ex1, FormatException ex...

4  Pythonのelse ins以外の複数の試着  ( Multiple try excepts followed by an else in python ) 
それらのすべてが成功した場合にのみ他の単一を引き起こすいくつかの連続したtry-except句をいくつか持っていますか? 例として: <事前> <コード> try: private.anodization_voltage_meter = Voltme...

6  Visual Studio 2005の下でC ++でexception_stack_overflow構造化例外をキャッチすることを保証する方法  ( How can i guarantee catching a exception stack overflow structured exception in ) 
背景 私は poof-crash [ 1 ]のアプリケーションを持っています。私はそれが吹き飛ばされたスタックが原因であることはかなり確実です。 アプリケーションはマルチスレッドです。 「<コード> Enable C++ Exceptions: Yes W...

1  Cocoaの例外報告フレームワーク[DUPLICATE]  ( Exception reporting frameworks for cocoa ) 
この質問はすでにここで回答を持っています Cocoa Appのクラッシュレポーター[閉じる] (7回答) ...

10  Pythonの `os.system`は例外をスローしますか?  ( Does pythons os system ever throw an exception ) 
Python Fameのextemed os.system が例外をスローしますか?もしそうなら、どれが? ...

2  ループのためのエラー/例外処理 - Python  ( Error exception handling in for loop python ) 
私はGoogle Cloud NL APIを使用していくつかの説明の感情を分析しています。一部の行については、エラー<コード> InvalidArgument: 400 The language vi is not supported for document...

29  NET 1.1の未処理の例外ハンドラ  ( Unhandled exception handler in net 1 1 ) 
.NET 1.1アプリケーションと私が任務してきたことの1つを維持しています。 Application.ThreadException および AppDomain.CurrentDomain.UnhandledException にハンドラを追加しました...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有