どちらの方法でも、長所と短所は何ですか。One Right Way(tm) はありますか?
9 に答える
アプリケーション全体でエラーの代わりに例外を使用する場合は、ErrorExceptionとカスタム エラー ハンドラーを使用できます (エラー ハンドラーのサンプルについては、ErrorException ページを参照してください)。この方法の唯一の欠点は、致命的ではないエラーが依然として例外をスローすることです。これは、キャッチされない限り常に致命的です。基本的に、error_reporting設定でそれらが抑制されていないE_NOTICE場合でも、アプリケーション全体が停止します。
私の意見では、ErrorException を使用することにはいくつかの利点があります。
- カスタム例外ハンドラーを使用すると、set_exception_handlerを使用して、エラーの場合でも適切なメッセージを表示できます。
- 既存のコードに影響を与えることはありません... trigger_errorおよびその他のエラー関数は引き続き正常に動作します。
E_NOTICEs とsをトリガーする愚かなコーディングの間違いを無視するのが本当に難しくなりE_WARNINGます。try/を使用catchして、PHP エラー (例外だけでなく) を生成する可能性のあるコードをラップできます。これは、@エラー抑制ハックの使用を回避する良い方法です。try { $foo = $_GET['foo']; } catch (ErrorException $e) { $foo = NULL; }キャッチされていないエラーが発生したときにユーザーにわかりやすいメッセージを表示したい場合は、スクリプト全体を単一の
try/ブロックでラップできます。catch(キャッチされていないエラーと例外のみがログに記録されるため、これは慎重に行ってください。)
「例外的な状況」で例外を使用する必要があります。つまり、メソッド doFoo() を呼び出すときに、それが実行されることを期待する必要があります。何らかの理由で doFoo がその仕事を実行できない場合は、例外を発生させる必要があります。
多くの古い php コードは、失敗が発生したときに false または null を返すアプローチをとっていましたが、これはデバッグを難しくし、例外はこのデバッグをはるかに簡単にします。
たとえば、DogFood オブジェクトの配列を返す getDogFood() というメソッドがあったとします。このメソッドを呼び出して、何か問題が発生したときに null を返す場合、呼び出し元のコードは、エラーが発生したために null が返されたかどうかをどのように判断できるでしょうか。それともドッグフードがないだけですか?
PHP の組み込みエラー ログを使用するレガシー コード ライブラリの処理に関しては、set_error_handler() 関数を使用してエラー ログをオーバーライドできます。これを使用して、一般的な例外を再スローすることができます。
すべてのコードが詳細な例外をスローするようになったので、それらをどうするかを自由に決めることができます。コードの一部で、それらをキャッチして別の方法を試したり、独自のログ機能を使用してそれらをログに記録したりすることができます。データベース、ファイル、電子メールなど、好みに応じてログを記録できます。つまり、例外はより柔軟です。
私は例外を使用するというアイデアが大好きですが、サードパーティのライブラリを使用することがよくあります。それらが例外を使用しない場合、問題に対して 3 ~ 4 の異なるアプローチが必要になります。Zend は例外を使用します。CakePHP はカスタム エラー ハンドラを使用し、ほとんどの PEAR ライブラリは PEAR::Error オブジェクトを使用します。
この点に関して、私には 1 つの真の方法がありました。カスタム エラー ハンドラー ルートは、この状況ではおそらく最も柔軟です。ただし、独自のコードのみを使用している場合、またはそれらを使用するライブラリを使用している場合は、例外を使用することをお勧めします。
残念なことに、PHP の世界ではまだ PHP4 の死を拒否しているため、例外のようなものは、ベスト プラクティスを表しているかもしれませんが、誰もが PHP4 と PHP4 の両方で動作できるようにするためのものをまだ書いているにもかかわらず、理解するのに非常に時間がかかりました。 5. うまくいけば、この大失敗は終わりつつありますが、終わる頃には、代わりに 6 と 5 の間の緊張状態になるでしょう...
/私は手で頭を抱えています...
状況によります。私は、ビジネス ロジックやアプリケーションの内部構造を記述しているときに例外を使用する傾向があり、バリデーターやその類のものには trigger_error を使用します。
論理レベルで例外を使用する利点は、そのようなエラーが発生した場合にアプリケーションが実行できるようにすることです。ビジネス ロジックにエラーの表示方法を知らせる代わりに、アプリケーションが選択できるようにします。
バリデータとその性質のものにtrigger_errorを使用することの長所は、たとえば、
try {
$user->login();
} catch (AuthenticationFailureException $e) {
set_error_handler("my_login_form_handler");
trigger_error("User could not be logged in. Please check username and password and try again!");
} catch (PersistenceException $pe) { // database unavailable
set_error_handler("my_login_form_handler");
trigger_error("Internal system error. Please contact the administrator.");
}
my_login_form_handler は文字列を整形し、要素をログイン フォームの上の可視領域に配置します。
明らかに、「1 つの正しい方法」はありませんが、これには多くの意見があります。;)
個人的には、例外ができないこと、つまり通知と警告(つまり、ログに記録したいものですが、エラー/例外と同じようにアプリケーションのフローを停止しないもの)にtrigger_errorを使用します(あるレベルでそれらをキャッチしたとしても) )))。
また、(例外が発生したメソッドの呼び出し元にとって) 回復不可能であると想定される状態、つまり重大なエラーに対しても例外を使用します。複雑でない方法で可能であれば、同じ意味の値を返す代わりに例外を使用しません。たとえば、ルックアップ メソッドを作成する場合、探しているものが見つからない場合は通常、EntityNotFoundException (または同等のもの) をスローするのではなく、null 値を返します。
したがって、私の経験則は次のとおりです。
- 何かが見つからないことが合理的な結果である限り、try-catch-clause を使用して処理するよりも、null 値 (またはその他の既定値) を返してチェックする方がはるかに簡単だと思います。
- 一方、それが重大なエラーであり、呼び出し元が回復する範囲外であることが判明しない場合でも、例外をスローします。
後者の場合に (エラーをトリガーするのではなく) 例外をスローする理由は、適切な名前の Exception サブクラスを使用すると、例外がより表現力豊かになるためです。PHP の標準ライブラリの例外を使用することは、使用する例外を決定する際の良い出発点であることがわかりました: http://www.php.net/~helly/php/ext/spl/classException.html
ただし、特定のケースに対してより意味的に正しい例外を取得するために、それらを拡張したい場合があります。
例外の考え方は洗練されており、エラー処理プロセスが非常にスムーズになります。ただし、これは適切な例外クラスがあり、チーム開発でもう 1 つ重要なことは "標準" 例外である場合にのみ適用されます。したがって、例外を使用する予定がある場合は、最初に例外の種類を標準化するか、一般的なフレームワークの例外を使用することをお勧めします。PHP (構造化コードと組み合わせたコード オブジェクト オリエンターを記述できる) に適用されるもう 1 つのことは、クラスを使用してアプリケーション全体を記述している場合です。オブジェクト指向で書いているなら、例外の方が断然いいです。結局のところ、エラー処理プロセスは、trigger_error などを除いてはるかにスムーズになると思います。
例外は、エラー状態/例外的な状況を通知する最新の堅牢な方法です。それらを使用してください:)
サードパーティのアプリケーション統合の時代に例外を使用することはお勧めできません。
自分のアプリを何か他のアプリと統合しようとした瞬間、または他の誰かのアプリを自分のアプリと統合しようとした瞬間に、サードパーティのプラグインのクラスが例外をスローした瞬間にアプリケーション全体が停止するためです。独自のアプリに本格的なエラー処理、ロギングが実装されている場合でも、サードパーティのプラグイン内の誰かのランダム オブジェクトが例外をスローし、アプリケーション全体がそこで停止します。
アプリケーションに、使用しているライブラリのエラーを補う手段がある場合でも....
例としては、ソーシャル ログイン プロバイダーがエラーを返したために例外をスローし、アプリ全体を不必要に強制終了するサード パーティのソーシャル ログイン ライブラリが考えられます (ハイブリッド認証)。つまり、アプリ全体があり、追加機能 (この場合はソーシャル ログイン) を提供するライブラリがあります。また、プロバイダーが認証しない場合 (独自のログイン システムに加えて、20 ほどの他のソーシャル ログイン プロバイダーなど)、アプリケーション全体が完全に停止します。そして、これらの問題を回避するためにサードパーティのライブラリを変更する必要が生じ、開発をスピードアップするためにサードパーティのライブラリを使用するポイントが失われます。
これは、PHP でエラーを処理するという哲学に関して、重大な設計上の欠陥です。それに直面しましょう - 今日開発されたほとんどのアプリケーションの反対側には、ユーザーがいます。イントラネット ユーザーであろうと、インターネット上のユーザーであろうと、システム管理者であろうと、問題ではありません。通常、ユーザーが存在します。
そして、前のページに戻って、ユーザーとして何をしようとしているのかについて暗闇の中でショットを撮る以外に、その時点でできることは何もないまま、アプリケーションがあなたの顔で死んでしまうのは悪いことです.開発側からの悪い習慣。言うまでもなく、多くの理由 (使いやすさからセキュリティまで) がユーザーに投げかけられるため、開発者だけが知っておくべき内部エラーです。
その結果、特定のサードパーティ ライブラリ (この場合はハイブリッド認証) を手放す必要があり、その理由だけでアプリケーションで使用しないようにする必要があります。Hybridauth は非常に優れたライブラリであるという事実にもかかわらず、明らかに多くの努力が費やされており、さまざまな機能が備わっています。
したがって、コードで例外を使用しないでください。現在実行しているコードがライブラリではなく、アプリケーションを実行する最上位のコードである場合でも、コードの全部または一部を他のプロジェクトに含めたり、一部を統合したりする必要がある可能性があります。またはそれ全体をあなたの他のコードまたはサードパーティのコードで。また、例外を使用した場合は、同じ状況に陥ります。コードの一部が提供する問題を処理する適切な手段があったとしても、アプリケーション/統合全体が直面して死んでしまいます。