web-dev-qa-db-ja.com

PHPでtry ... catchブロックを効率的に使用する方法

私は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;
 }

しかし、私がやっていることが良い習慣なのか、例外をキャッチするための怠wayな方法なのかはわかりません。

私の仮定は、例外が特別な処理を必要とする場合にのみ、独自のtry/catchブロックが必要です。

だから私の質問は:

データベーストランザクションごとにtry/catchブロックを使用する利点はありますか?または、同じtry/catchブロックに複数のデータベーストランザクションをグループ化しても問題はありませんか?

Try/catchブロックをネストしても大丈夫ですか?ありがとう!

編集

Returnステートメントは主にデモンストレーションのみを目的としていましたが、AJAXリクエストをそのメソッドに送信し、JavascriptがJSONオブジェクトを期待しているため、catch()でreturnも使用しています。例外が発生した場合、空のJSONエンコードされた配列を返します。私の例では、特定のコードを追加しても値を追加しないと考えました。

74
ILikeTacos

重要な注意

次の説明では、上記の例のように構造化されたコードについて話していることを前提としています。どの選択肢を選択したとしても、例外によってメソッドは途中で何でも論理的に停止します。


tryブロック内のどのステートメントが例外をスローしても同じことをしようとする限り、単一の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"
    }
}
89
Jon

後世のために、答えは遅すぎるかもしれません。変数の戻り値を確認し、例外をスローする必要があります。その場合、プログラムは例外が発生している場所から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();

}
21
kodepet

単一のtry catchブロックの方が読みやすくなっています。その重要性がエラーの種類を特定する場合、例外をカスタマイズすることをお勧めします。

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

スローされた例外は、失敗した操作の後のさらなる操作の実行を妨げるため、複数の操作に単一のブロックを使用することに理由はありません。少なくとも、キャッチされた例外から失敗した操作を結論付けることができる限り。一部の操作がnot処理されていれば問題ありません。

しかし、例外を返すことは意味をなさないと思います。関数の戻り値は、例外ではなく、何らかのアクションの期待される結果でなければなりません。呼び出し元のスコープで例外に対応する必要がある場合は、関数内で例外をキャッチせず、呼び出し元のスコープで例外を再スローするか、デバッグロギングなどを行った後の処理のために例外を再スローします。

8
arkascha

例外がスローされると、実行はすぐに停止され、catch{}ブロックで続行されます。つまり、データベース呼び出しを同じtry{}ブロックに配置し、$tableAresults = $dbHandler->doSomethingWithTableA();が例外をスローした場合、$tableBresults = $dbHandler->doSomethingElseWithTableB();は発生しません。 2番目のオプションでは、実行が再開されたときにcatch{}ブロックの後にあるため、$tableBresults = $dbHandler->doSomethingElseWithTableB();は引き続き発生します。

すべての状況に理想的なオプションはありません。関係なく2番目の操作を続行する場合は、2つのブロックを使用する必要があります。 2番目の操作を行わないことが許容される(または望ましい)場合は、1つだけを使用する必要があります。

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

単一のtry catchブロックで、特定のエラーについて独自のメッセージで表示したい場合は、異なるcatchブロックでエラーをキャッチすることをお勧めします。

1
Amar Agrawal

以下のような1つのtry catchブロックで複数行の実行を書くのに問題はありません

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

install_engineまたはinstall_break関数のいずれかで実行が行われた瞬間、コントロールはcatch関数に渡されます。もう1つの推奨事項は、例外を適切に食べることです。つまり、die('Message')と書く代わりに、例外処理を適切に行うことを常にお勧めします。エラー処理ではdie()関数を使用することを考えますが、例外処理では使用しないでください。

複数のtry catchブロックを使用する必要がある場合異なるコードブロック例外に異なるタイプの例外を表示したい場合、または以下のようにcatchブロックから例外をスローしようとしている場合、複数の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')
}

さまざまなケースでtry catchブロックを使用する方法の詳細については、 PHP Try Catch のブログを参照してください。

0