多くの PHP 内部メソッドは失敗を伝えるためにエラーを使用します。 これらのエラーはトラップされ、対処される必要があるでしょう。 CakePHP はエラーが起きるとそれを表示しまたはログに記録する既定のエラートラップを備えています。 この同じエラーハンドラーがあなたのアプリケーション中のコントローラーや他の部分から キャッチされなかった例外をつかまえるために用いられます。
エラーの設定はあなたのアプリケーションの config/app.php ファイル中で行われます。
既定では CakePHP はエラーをトラップし、そのエラーを表示/ログに記録するために
ErrorHandler
または ConsoleErrorHandler
クラスを使用します。
エラー処理はあなたのアプリケーション用のエラー処理を調整するためにいくつかのオプションを受け入れます:
errorLevel
- int - あなたが捕捉したいエラーレベル。 組み込みの PHP エラー定数を使い、捕捉したいエラーレベルを選択するためにビットマスクします。trace
- bool - ログファイル中にエラーのスタックトレースを含めます。 スタックトレースはログ中の各エラーの後に含まれるでしょう。 これはどこで/いつそのエラーが引き起こされたかを見つけるために役に立ちます。exceptionRenderer
- string - キャッチされなかった例外を描画する役目を担うクラス。 もしもカスタムクラスを選択する場合は src/Error 中にそのクラスのファイルを置くべきです。 このクラスはrender()
メソッドを実装する必要があります。log
- bool -true
の時、 :php:class:`Cake\\Log\\Log` によって例外とそのスタックトレースがログに記録されます。skipLog
- array - ログに記録されるべきではない例外クラス名の配列。 これは NotFoundException や他のありふれた、でもログにはメッセージを残したくない例外を除外するのに役立ちます。extraFatalErrorMemory
- int - 致命的エラーが起きた時にメモリーの上限を増加させるためのメガバイト数を設定します。 これはログの記録やエラー処理を完了するために猶予を与えます。
エラーハンドラーは既定では、 debug
が true
の時にエラーを表示し、
debug
が false
の時にエラーをログに記録します。
いずれも捕捉されるエラータイプは errorLevel
によって制御されます。
致命的エラーのハンドラーは debug
レベルや errorLevel
とは独立して呼び出されますが、
その結果は debug
レベルによって変わるでしょう。
致命的エラーに対する既定のふるまいは内部サーバーエラーページ (debug
無効)
またはエラーメッセージ、ファイルおよび行を含むページ (debug
有効) を表示します。
Note
もしカスタムエラーハンドラーを使うなら、サポートされるオプションはあなたのハンドラーに依存します。
あなたはコールバックタイプからエラーハンドラーを作り出すことができます。
たとえばあなたのエラーを処理するために AppError
というクラスを使うことができます。
BaseErrorHandler
を継承することでエラーを処理するためのカスタムロジックを提供できます。
一つ例は:
// config/bootstrap.php の中で use App\Error\AppError; $errorHandler = new AppError(); $errorHandler->register(); // src/Error/AppError.php の中で namespace App\Error; use Cake\Error\BaseErrorHandler; class AppError extends BaseErrorHandler { public function _displayError($error, $debug) { echo 'エラーがありました!'; } public function _displayException($exception) { echo '例外がありました!'; } }
BaseErrorHandler
は二つの抽象メソッドを定義しています。
_displayError()
はエラーが引き起こされた時に使われます。
_displayException()
メソッドはキャッチされなかった例外がある時に呼ばれます。
既定のエラーハンドラーは致命的エラーを例外に変換し エラーページを描画するための例外処理方法を再利用します。 もし標準のエラーページを表示したくない場合は、あなたはそれをオーバーライドできます。
// config/bootstrap.php の中で use App\Error\AppError; $errorHandler = new AppError(); $errorHandler->register(); // src/Error/AppError.php の中で namespace App\Error; use Cake\Error\BaseErrorHandler; class AppError extends BaseErrorHandler { // 他のメソッド public function handleFatalError($code, $description, $file, $line) { return '致命的エラーが発生しました'; } }
.. php:namespace:: Cake\Network\Exception
CakePHP にはいくつかの例外クラスがあります。 組み込みの例外処理ではキャッチされなかったあらゆる例外を捕捉しページを描画するでしょう。 例外は 400 番台のコードは使わず、内部サーバーエラーとして扱われるでしょう。
CakePHP 内部のいくつかの組み込みの例外には、内部的なフレームワークの例外の他に、 HTTP メソッド用のいくつかの例外があります。
.. php:exception:: BadRequestException 400 Bad Request エラーに使われます。
.. php:exception:: UnauthorizedException 401 Unauthorized エラーに使われます。
.. php:exception:: ForbiddenException 403 Forbidden エラーに使われます。
.. versionadded:: 3.1 InvalidCsrfTokenException が追加されました。
.. php:exception:: InvalidCsrfTokenException 無効な CSRF トークンによって引き起こされた 403 エラーに使われます。
.. php:exception:: NotFoundException 404 Not Found エラーに使われます。
.. php:exception:: MethodNotAllowedException 405 Method Not Allowed エラーに使われます。
.. php:exception:: NotAcceptableException 406 Not Acceptable エラーに使われます。 .. versionadded:: 3.1.7 NotAcceptableException が追加されました。
.. php:exception:: ConflictException 409 Conflict エラーに使われます。 .. versionadded:: 3.1.7 ConflictException が追加されました。
.. php:exception:: GoneException 410 Gone エラーに使われます。 .. versionadded:: 3.1.7 GoneException が追加されました。
HTTP 4xx エラーステータスコードの詳細は RFC 2616 をご覧ください。
.. php:exception:: InternalErrorException 500 Internal Server Error に使われます。
.. php:exception:: NotImplementedException 501 Not Implemented エラーに使われます。
.. php:exception:: ServiceUnavailableException 503 Service Unavailable エラーに使われます。 .. versionadded:: 3.1.7 Service Unavailableが追加されました。
HTTP 5xx エラーステータスコードの詳細は RFC 2616 をご覧ください。
失敗の状態や HTTP エラーを示すためにあなたのコントローラーからこれらの例外を投げることができます。 HTTP の例外の使用例はアイテムが見つからなかった場合に 404 ページを描画することでしょう。
use Cake\Network\Exception\NotFoundException; public function view($id = null) { $article = $this->Articles->findById($id)->first(); if (empty($article)) { throw new NotFoundException(__('記事が見つかりません')); } $this->set('article', $article); $this->set('_serialize', ['article']); }
HTTP エラー用の例外を使うことで、あなたのコードを綺麗にし、 かつ RESTful なレスポンスをアプリケーションのクライアントやユーザーに返すことができます。
加えて、以下のフレームワーク層の例外が利用可能で、 そしていくつかの CakePHP のコアコンポーネントから投げられるでしょう。
.. php:namespace:: Cake\View\Exception
.. php:exception:: MissingViewException 選択されたビュークラスが見つかりません。
.. php:exception:: MissingTemplateException 選択されたテンプレートファイルが見つかりません。
.. php:exception:: MissingLayoutException 選択されたレイアウトが見つかりません。
.. php:exception:: MissingHelperException 選択されたヘルパーが見つかりません。
.. php:exception:: MissingElementException 選択されたエレメントのファイルが見つかりません。
.. php:exception:: MissingCellException 選択されたセルクラスが見つかりません。
.. php:exception:: MissingCellViewException 選択されたビューファイルが見つかりません。
.. php:namespace:: Cake\Controller\Exception
.. php:exception:: MissingComponentException 設定されたコンポーネントが見つかりません。
.. php:exception:: MissingActionException 要求されたコントローラーのアクションが見つかりません。
.. php:exception:: PrivateActionException private/protected/_ が前置されたアクションへのアクセス。
.. php:namespace:: Cake\Console\Exception
.. php:exception:: ConsoleException コンソールライブラリークラスがエラーに遭遇しました。
.. php:exception:: MissingTaskException 設定されたタスクが見つかりません。
.. php:exception:: MissingShellException シェルクラスが見つかりません。
.. php:exception:: MissingShellMethodException 選択されたシェルクラスが該当の名前のメソッドを持っていません。
.. php:namespace:: Cake\Database\Exception
.. php:exception:: MissingConnectionException モデルの接続がありません。
.. php:exception:: MissingDriverException データベースドライバーが見つかりません。
.. php:exception:: MissingExtensionException データベースドライバーのための PHP 拡張がありません。
.. php:namespace:: Cake\ORM\Exception
.. php:exception:: MissingTableException モデルのテーブルが見つかりません。
.. php:exception:: MissingEntityException モデルのエンティティーが見つかりません。
.. php:exception:: MissingBehaviorException モデルのビヘイビアーが見つかりません。
.. php:exception:: PersistenceFailedException :php:meth:`Cake\\ORM\\Table::saveOrFail()` や :php:meth:`Cake\\ORM\\Table::deleteOrFail()` を使用しましたが、 エンティティーは、保存/削除されませんでした。 .. versionadded:: 3.4.1 PersistenceFailedException は追加されました。
.. php:namespace:: Cake\Datasource\Exception
.. php:exception:: RecordNotFoundException 要求されたレコードが見つかりません。 これは HTTP レスポンスヘッダーに 404 を設定しもするでしょう。
.. php:namespace:: Cake\Routing\Exception
.. php:exception:: MissingControllerException 要求されたコントローラーが見つかりません。
.. php:exception:: MissingRouteException 要求された URL はルーティングの逆引きができないか解析できません。
.. php:exception:: MissingDispatcherFilterException ディスパッチャーフォルターが見つかりません。
.. php:namespace:: Cake\Core\Exception
.. php:exception:: Exception CakePHP での基底例外クラス。 CakePHP によって投げられるすべてのフレームワーク層の例外はこのクラスを継承するでしょう。
これらの例外クラスはすべて :php:exc:`Exception` を継承します。 Exception を継承することにより、あなたは独自の‘フレームワーク’エラーを作ることができます。 CakePHP が投げるであろう標準の例外もすべて Exception を継承します。
.. php:method:: responseHeader($header = null, $value = null) :php:func:`Cake\\Network\\Request::header()` 参照
すべての Http と Cake の例外は Exception クラスを継承し、 レスポンスにヘッダーを追加するためのメソッドを持っています。 RFC2616 MethodNotAllowedException は言っています。
「レスポンスは要求されたリソースに有効なメソッドの一覧を含むAllowヘッダーを含まなければ【ならない】」
失敗の状態を示すためにあたなのコントローラーのアクションからあらゆる HTTP 関連の例外を投げることができます。 たとえば:
use Cake\Network\Exception\NotFoundException; public function view($id = null) { $article = $this->Articles->findById($id)->first(); if (empty($article)) { throw new NotFoundException(__('記事が見つかりません')); } $this->set('article', 'article'); $this->set('_serialize', ['article']); }
上記は :php:exc:`NotFoundException` をキャッチして処理するための例外ハンドラーを設定するでしょう。 既定ではエラーページを作り、例外をログに記録するでしょう。
.. php:class:: ExceptionRenderer(Exception $exception)
ErrorController
の手助けをする ExceptionRenderer クラスは
あなたのアプリケーションによって投げられたすべての例外のためのエラーページを処理します。
エラーページのビューは src/Template/Error/ に配置されます。
すべての 4xx と 5xx エラー用のテンプレートファイル error400.ctp と error500.ctp がそれぞれ使われます。
必要に応じてそれらをカスタマイズすることができます。
既定では src/Template/Layout/error.ctp もエラーページに使われます。
たとえばもしも、他のレイアウト src/Template/Layout/my_error.ctp をエラーページに使いたい場合、
単純にエラー用ビューを編集して $this->layout = 'my_error';
という文を
error400.ctp と error500.ctp に追加してください。
各フレームワーク層の例外はコアのテンプレートに置かれた個別のビューファイル持っていますが それらは開発中の間にのみ使われますのでそれらのカスタマイズに悩む必要はまったくありません。
.. index:: application exceptions
組み込みの SPL の例外 、 Exception
そのもの、
または :php:exc:`Cake\\Core\\Exception\\Exception` のいずれかを使って
あなた独自のアプリケーション例外を作ることができます。
もしあなたのアプリケーションが以下の例外を含んでいたなら:
use Cake\Core\Exception\Exception; class MissingWidgetException extends Exception {};
src/Template/Error/missing_widget.ctp を作ることで、素晴らしい開発用エラーを提供できるでしょう。
本番モードでは、上記のエラーは 500 エラーとして扱われるでしょう。
:php:exc:`Cake\\Core\\Exception\\Exception` のコンストラクターが継承されており、
データの連想配列を渡すことができます。それらの連想配列はメッセージテンプレートに差し込まれ、
開発モードでのエラーを表示するため使われるビューにも同様に差し込まれます。
これにより、エラー用の多くのコンテキスト提供して、データ豊富な例外を作ることができます。
ネイティブの __toString()
メソッドを正常に動作させるメッセージテンプレートを提供することもできます。
use Cake\Core\Exception\Exception; class MissingWidgetException extends Exception { protected $_messageTemplate = '%s が見当たらないようです。'; } throw new MissingWidgetException(['widget' => 'Pointy']);
組み込みの例外ハンドラーにキャッチされた時、あなたはエラービューテンプレート中に $widget
変数を得られるでしょう。
加えてもしその例外を文字列にキャストするかその getMessage()
メソッドを使うと %s が見当たらないようです。
を得られるでしょう。
これにより、ちょうど CakePHP が内部的に使っているように、あなた独自の富んだ開発用エラーを手早く作ることができます。
例外を生成する際にコードを変えることでカスタム HTTP ステータスコードを作ることができます。
throw new MissingWidgetHelperException('それはここにはありません', 501);
これは 501 のレスポンスコードを作るでしょうが、あなたが望むあらゆる HTTP ステータスコードを使うことができます。 開発中は、もしあなたの例外が特定のテンプレートを持っておらず、かつ 500 番以上のコードを使うと error500.ctp テンプレートが表示されるでしょう。他のあらゆるエラーコードでは error400.ctp テンプレートになるでしょう。 もしカスタムの例外用のエラーテンプレートを定義している場合、そのテンプレートが開発中は使われるでしょう。 もし本番でもあなた独自の例外処理方法が欲しい場合は次の節を参照してください。
あなたはいくつかの方法でアプリケーション固有の例外処理を実装することができます。 各方法ごとに、例外処理工程における異なる量の制御権をあなたに与えます。
- 独自のカスタムエラーハンドラーの作成と登録
- CakePHP によって提供される
BaseErrorHandler
の継承 - 既定のエラーハンドラーに
exceptionRenderer
オプションの設定
次の節では、さまざまな方法とそれらが各々持つ利点について詳述します。
独自の例外ハンドラーの作成は、例外処理工程における全制御権をあなたに与えます。
この場合には、あなたは set_exception_handler
を自分で呼ばなければならないでしょう。
:ref:`error-configuration` の節にこの例があります。
もし例外処理の制御権を得る必要はないものの、どのように例外が描画されるを変更したい場合は
例外ページを描画するであろうクラスを選択するために
config/app.php 中の exceptionRenderer
オプションを使うことができます。
// src/Error/AppExceptionRenderer.php の中で namespace App\Error; use Cake\Error\ExceptionRenderer; class AppExceptionRenderer extends ExceptionRenderer { public function missingWidget($error) { return 'おっとウィジェットが見つからない!'; } } // config/app.php の中で 'Error' => [ 'exceptionRenderer' => 'App\Error\AppExceptionRenderer', // ... ], // ...
上記は MissingWidgetException
型のあらゆる例外を処理し、
それらのアプリケーション例外を表示/処理するためのカスタム処理ができるようにします。
例外処理メソッドは、引数として処理される例外を受け取ります。
あなたのカスタム例外処理は文字列または Response
オブジェクトを返すことができます。
Response
オブジェクトの返却はそれのレスポンスに対する全制御権をあなたに与えます。
Note
カスタムレンダラーはコンストラクターで例外を受け取るのを期待し、render メソッドを実装します。
もしもカスタム例外処理を使っている場合、レンダラーの設定変更は効果がありません。 あなたの実装の中であなたがそれを参照しない限り。
慣例では CakePHP はもし存在すれば App\Controller\ErrorController
を使います。
このクラスを実装することで、エラーページ出力のカスタマイズの設定に依存しない方法を提供します。
もしあなたがカスタム例外レンダラーを使っているのであれば、
カスタマイズコントローラーを返すために _getController()
メソッドを使うことができます。
例外レンダラーの中で _getController()
を実装することにより
あなたが望むあらゆるコントローラーを使うことができます。
// src/Error/AppExceptionRenderer の中で namespace App\Error; use App\Controller\SuperCustomErrorController; use Cake\Error\ExceptionRenderer; class AppExceptionRenderer extends ExceptionRenderer { protected function _getController($exception) { return new SuperCustomErrorController(); } } // config/app.php の中で 'Error' => [ 'exceptionRenderer' => 'App\Error\AppExceptionRenderer', // ... ], // ...
エラーコントローラーは、カスタムであろうと慣例のままであろうと、エラーページの表示に使われ、 すべての標準のリクエストライフサイクルイベントを受け取ります。
組み込みの例外処理を使うと、 config/app.php 中で log
オプションに true
を設定することで
ErrorHandler によって対処されるすべての例外をログに記録することができます。
これを有効にすることで :php:class:`Cake\\Log\\Log` と設定済みのロガーに各例外の記録が残るでしょう。
Note
もしもカスタム例外処理を使っている場合、この設定は効果がないでしょう。 あなたの実装の中であなたがそれを参照しない限り。