CakePHP2でエラーのレイアウトを切り替える

エラー時のデフォルトレイアウトってerror.ctpじゃなくてdefault.ctpなんだ。。

CakePHP2で独自のエラーを適用するで、カスタムエラーハンドラの作り方は分かったけど、エラー発生時のテンプレート側の設定はこのエラーハンドラでは行わないらしい。

http://book.cakephp.org/2.0/en/development/exceptions.html
↑ここら辺を調べると、Exceptionのrendererあたりの設定で対応できそう。

とりあえずrendererを改造するにはapp/Lib/Errorに自作のクラスを設置して~って書いてあるので、ExceptionRendererを基底としたAppExceptionRendererクラスを作成する。

<?php
App::uses ('ExceptionRenderer' , 'Error' );
/**
 * アプリケーション独自の例外View
 *
 * @package app.Lib
 */
class AppExceptionRenderer extends ExceptionRenderer {
}

ExceptionRendererを拡張する前に、このクラスが何をやっているのか調べてみたのだが、どうやらerror.ctpレイアウトは通常のエラーメッセージ出力関数(_outputMessage)に例外がないと呼び出されないらしい。なかなかお目にかかれないわけだ。
で、今回はエラー出力時のデフォルトをerror.ctpに切り替えたいので、_getControllerあたりを調べてみる

protected function _getController($exception) {
    App:: uses('CakeErrorController', 'Controller');
    if (!$request = Router::getRequest( true)) {
      $request = new CakeRequest();
    }
    $response = new CakeResponse(array('charset' => Configure::read(App.encoding')));
    try {
        if (class_exists('AppController' )) {
            $controller = new CakeErrorController($request, $response);
        }
    } catch (Exception $e) {
    }
    if (empty ($controller)) {
        $controller = new Controller($request, $response);
        $controller-> viewPath = 'Errors';
    }
    return $controller;
}

エラー発生時にエラー用のコントローラー(CakeErrorController)が呼び出され、ここにセットされたviewPathやlayoutが最終的にエラー出力時のテンプレートになってくるようなので、これを弄ればなんとかなりそう。
ということで以下のようにしてみた。

<?php
App::uses ('ExceptionRenderer' , 'Error' );

class AppExceptionRenderer extends ExceptionRenderer {

    protected function _getController($exception) {
        $controller = parent ::_getController($exception);
        $controller-> layout = 'error';
        return $controller;
    }
}

で、実際にエラーを起こしてみたらちゃんとerrorのレイアウトを見に行くようになっていた。