Yiiのエラー処理スキーム

みなさんこんにちは!

Yiiのエラー処理プロセスは、このフレームワークを使用した最初の日から完全に透過的ではありませんでした。 特別なセクションError Handlingのドキュメントの存在にもかかわらず。 どのような場合にどのビューが使用されるか、Ajaxまたはデバッグモードがどのように影響するか、なぜerrorActionが必要か、例外を処理するときの違いは何ですか?

その結果、ドキュメントとフレームワークのソースコードを掘り下げた後、エラー処理のための視覚的なスキームを描きました。

カットの下で、スキーム自体とそれにいくつかのコメント。





0.エラーレベル


そのため、デフォルトでは、Yiiは警告および通知エラー、およびキャッチさなかった例外のみを処理します。 致命的なエラーを処理するには、register_shutdown_functionを使用します(詳細は記事の最後にあります)。



1.行こう!


警告が発生した場合、またはキャッチされなかった例外が発生した場合、2つの定数がそれに応じて設定されていれば、Yiiはそれらを処理します。

YII_ENABLE_ERROR_HANDLER = true YII_ENABLE_EXCEPTION_HANDLER = true
      
      





同様のシナリオでYiiでエラーと例外の両方が処理されます。 しかし、私が言及する特定の違いがあります。

画像



2.ロギング


まず、エラーまたは例外情報がログに書き込まれます-Yii :: log()関数。



3.イベントコール


次に、 onErroronException )イベントが発生します。 これらのイベントにユーザー定義のハンドラーがある場合、呼び出され、必要なアクションを実行し、イベントのさらなる処理を停止できます( event-> handled = trueを設定することにより)。 次のようにハンドラーを切断できます。

 $app->onError=function($event) { ... }
      
      





またはattachEventHandler()メソッドを介して。



4.接続ErrorHandler


イベント処理が続行する場合( event-> handled = false )、errorHandler yiiアプリケーションの標準コンポーネントが機能します(デフォルトでは常にnullではありません)。 対応するhandleError()またはhandleException()メソッドを呼び出します。 これらの同様の方法の中で、エラーと例外(Yii 1.1.9の現在のバージョンで利用可能)の間に重要な違いがあります:



これに応じて、最も単純なhtml-error出力がapp-> displayError()経由で呼び出されるか、ErrorHandlerコンポーネントのトリッキーなrender()関数が呼び出されます。

以前は、ajaxのチェックもhandleException()で行われていましたが、1.1.9で削除されたため、ajaxリクエスト(たとえば、jsonを返す)の例外を処理しやすくなりました。



5. ErrorHandlerでのトリッキーなレンダリング


ErrorHandler-> render()関数を「tricky」と呼びます。これは、コントローラーの通常のレンダリングとは少し異なる動作をするためです。



ビューは次の場所で順番に検索されます。

1.テーマ/ ThemeName /ビュー/システム

2.保護/ビュー/システム

3.フレームワーク/ビュー



6.カスタムエラー表示


errorActionが設定されている場合(たとえば、configの "site / error")、このメソッドは、実稼働モードでのカスタム表示エラーと例外の表示に使用されます。 ajaxリクエストと非ajaxリクエストについては、異なる結論を出すのが便利です。 また、ここでは、 ビュー/サイト/error.php (ページの完全なhtmlコードを含むviews / system / errorXXX.phpとは異なります)を介して、アプリケーションの一般的なレイアウトで出力を実行できることに注意してください。



あとがき:致命的なエラー処理


しかし、致命的なエラーはどうでしょうか? register_shutdown_functionによるインターセプトは、現在Yiiでは実装されていません。 現在プロジェクトで使用しているソリューションは次のとおりです。

1.アプリケーションを初期化するときに、シャットダウンハンドラーを登録します

2.ハンドラーで、 error_get_last()を使用してエラーとそのレベルを確認します。 エラーがすでに処理されている場合、NULLが返されます

3. app-> handleError()で処理メカニズム全体を実行します。つまり、 サーキットの始まりに近い



error_get_last()を使用する場合、この関数は演算子の前のerror_reportingディレクティブと@記号を無視することに注意することが重要です。 表示されず、処理されないE_NOTICEを含めることができます(たとえば、セッションの実行中に@session_start()を呼び出します)。

したがって、ハンドラーでは、致命的なエラーのみをチェックします。

また、 errorAction = nullを設定します。次に、図から明らかなように、システムビューerror.phpが表示されます。これは、エラーが繰り返される可能性が高い別のコントローラーアクションを実行するよりも信頼性が高くなります。

 class WebApplication extends CWebApplication { protected function init() { register_shutdown_function(array($this, 'onShutdownHandler')); parent::init(); } public function onShutdownHandler() { // 1. error_get_last() returns NULL if error handled via set_error_handler // 2. error_get_last() returns error even if error_reporting level less then error $e = error_get_last(); $errorsToHandle = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING; if(!is_null($e) && ($e['type'] & $errorsToHandle)) { $msg = 'Fatal error: '.$e['message']; // it's better to set errorAction = null to use system view "error.php" instead of run another controller/action (less possibility of additional errors) yii::app()->errorHandler->errorAction = null; // handling error yii::app()->handleError($e['type'], $msg, $e['file'], $e['line']); } } }
      
      







おわりに


私の意見では、Yiiのエラー処理プロセスはそれほど単純ではありませんが、非常に柔軟性があります。 私はあなたのコメントとアドバイスを聞いてうれしいです。

ご清聴ありがとうございました!



UPD:

スキームをPDF形式で投稿しました



All Articles