エラーハンドリング ============== Yii は PHP 5 の例外メカニズムを元にした完全なエラーハンドリングを提供します。 アプリケーションがユーザのリクエストによって呼び出された時、アプリケーションは、[handleError|CApplication::handleError] メソッドを PHP の warning と notice を扱うために登録し、[handleException|CApplication::handleException] メソッドを PHP の exeption (例外) を扱うために登録します。 したがって、もしアプリケーションの実行時に PHP の warning や notice、キャッチされない例外が発生した場合は、どちらかのエラーハンドラが制御を握って、必要なエラーハンドリングの処理を開始します。 > Tip|ヒント: エラーハンドラは、アプリケーションのコンストラクタで PHP 関数である [set_exception_handler](http://php.net/manual/ja/function.set-exception-handler.php) と [set_error_handler](http://php.net/manual/ja/function.set-error-handler.php) によって登録されます。 もし不要な場合は、[エントリスクリプト](/doc/guide/basics.entry) で `YII_ENABLE_ERROR_HANDLER` と `YII_ENABLE_EXCEPTION_HANDLER` の定数を false として定義する事で対応できます。 デフォルトでは、[handleError|CApplication::handleError] (または [handleException|CApplication::handleException]) は [onError|CApplication::onError] イベント (または [onException|CApplication::onException] イベント) を発生させます。 もしエラー (あるいは例外) がイベントハンドラによって処理されなかった場合は、エラーイベント (または例外イベント) は、[errorHandler|CErrorHandler] アプリケーションコンポーネントに助けを求めます。 例外の発生 ------------------ Yii において例外を発生させる仕方は、通常の PHP の例外を発生させる方法と異りません。 以下の文法を例外を発生させるために使用できます: ~~~ [php] throw new ExceptionClass('ExceptionMessage'); ~~~ Yii は三つの例外クラスを定義しています。 [CException], [CDbException], そして [CHttpException] です。 [CException] は包括的な例外クラスです。 [CDbException] はデータベースに関係する何らかの操作によって引き起こされた例外を表します。 [CHttpException] はエンドユーザに表示されるべき例外を表すもので、HTTP ステータスコードを表す [statusCode|CHttpException::statusCode] プロパティを持ちます。 例外をどのように表示すべきかは、以下で説明するように、例外のクラスによって決ります。 > Tip|ヒント: [CHttpException] 例外を発生させることは、ユーザの操作ミスによって生じたエラーを報告するシンプルな方法です。 例えば、もしユーザが無効な post ID の URL を要求した場合は、以下のような単純な方法で 404 error (page not found) を表示する事が出来ます: ~~~ [php] // もし要求された post ID が無効な場合 throw new CHttpException(404,'指定された記事が見つかりません。'); ~~~ エラーの表示 ----------------- エラーの処理が [CErrorHandler] アプリケーションコンポーネントまで流れてくると、エラーを表示するために相応しいビューが選ばれます。 エラーが [CHttpException] のように、エンドユーザへ表示すべきタイプのものだった場合、`errorXXX` という名前のビューが使用されます。 この `XXX` の部分は HTTP ステータスコード (例えば 400, 404, 500など) を表します。 エラーが内部的なもので、開発者にのみ表示するべきものであった場合は、`exeptions` という名前のビューが使用されます。 その場合は、完全なコールスタックとともにエラー行の情報が表示されます。 > Info|情報: アプリケーションが [実運用モード](/doc/guide/basics.entry#sec-2) で実行された時、内部的なエラーを含む全てのエラーは `errorXXX` というビューを使用して表示されます。 これは、エラーのコールスタックが機密に関わる情報を含む可能性があるためです。 この場合は、開発者はエラーの真の原因を究明するために、エラーログに頼らなければなりません。 [CErrorHandler] は下記の順序で対応するビューファイルを探します: 1. `WebRoot/themes/ThemeName/views/system`: 現在アクティブになっているテーマの中の `system` ビューディレクトリ 2. `WebRoot/protected/views/system`: アプリケーションのデフォルトの `system` ビューディレクトリ 3. `yii/framework/views`: Yii フレームワークによって供給される標準のシステムビューディレクトリ したがって、もしエラーの表示をカスタマイズしたい場合は、アプリケーションかテーマのシステムビューディレクトリーにエラービューファイルを作成する事で容易に実現可能です。 それぞれのビューファイルは、大部分が HTML コードで成り立った通常の PHP スクリプトです。 詳細は framework の `view` ディレクトリにあるデフォルトのビューファイルを参考にして下さい。 アクションを用いたエラーハンドリング ------------------------------- Yii では [コントローラアクション](/doc/guide/basics.controller#sec-4) を用いてエラー表示をすることが出来ます。 これを行うために、アプリケーション構成ファイル中のエラーハンドラを以下のように構成します。 ~~~ [php] return array( ...... 'components'=>array( 'errorHandler'=>array( 'errorAction'=>'site/error', ), ), ); ~~~ 上記において、[CErrorHandler::errorAction] プロパティは `site/error` を示すようにします。 これは `SiteController` コントローラの `error` アクションを意味します。 もし違う名前のコントローラ/アクションを使いたい場合はそれを用いても構いません。 `error` アクションは以下のように記述されます。 ~~~ [php] public function actionError() { if($error=Yii::app()->errorHandler->error) $this->render('error', $error); } ~~~ このアクションにおいて、最初に詳細なエラー情報を [CErrorHandler::error] から入手します。 もしこれが空でない場合は、このエラー情報にもとづいて `error` ビューを表示します。 [CErrorHandler::error] で返されるエラー情報は以下のフィールドを持つ配列です。 * `code`: HTTPステータスコード (例: 403, 500) * `type`: エラータイプ (例: [CHttpException], `PHP Error`) * `message`: エラーメッセージ * `file`: エラーの起きたPHPスクリプトファイル名 * `line`: エラーの起きた行番号 * `trace`: エラーのコールスタック * `source`: エラーの起きたソースコード > Tip|ヒント: [CErrorHandler::error] が空であるかないかをチェックする理由は、`error` アクションは、エラーが無い場合でもエンドユーザによって要求されることがあるためです。 `$error` という配列をビューに渡しているため、フィールドが自動的に個々の変数に展開されます。 従って、ビューにおいてはそれらの変数は例えば `$code`, `$type` として直接にアクセスすることができます。 メッセージのログ処理 --------------- エラーが発生した際、`error` レベルのメッセージは常に記録されます。 もし PHP の warning か notice によってエラーが発生した場合、メッセージはカテゴリー `php` と共に記録されます。 もしエラーがキャッチされていない例外として発生した際、カテゴリーは `exception.ExceptionClassName` の様になるでしょう ([CHttpException] における [statusCode|CHttpException::statusCode] もまたカテゴリーに追加されるでしょう)。 このように、[ロギング](/doc/guide/topics.logging) 機能を利用して、アプリケーションの実行の間に起きるエラーをモニターすることが出来ます。