CakePHPで独自の例外を定義する

APIで例外の返却値が既に決まっている場合、返却値を独自に変更します。今回は、表示部分を下のような感じにしたいと思い、そのために変更したいので、ExceptionとExceptionRendererを定義しました。

{
meta: {
url: "/api/systems.json",
method: "GET"
},
error: {
message: "Failed"
}
}

大体の流れはこんな感じです。

  1. app/Lib/Error/ApiException.phpとapp/Lib/Error/AppExceptionRenderer.phpを作成
  2. app/Lib/Error/error_api.ctpを作成
  3. app/Config/core.phpで読み込み

1.app/Lib/Error/ApiException.phpとapp/Lib/Error/AppExceptionRender.phpを作成

ここで例外部分を定義しています。特に変わったことはしてないです。

<?php
//app/Lib/Error/ApiException.php
class ApiException extends HttpException {
    public function __construct($message = null,$code = 400) {
        if (empty($message)) {
            $message = 'Api Error';
        }   
        parent::__construct($message, $code);
    }   
}

ここでは、ExceptionRenderer部分を定義しています。ApiExceptionのインスタンスの場合はに$this->methodで'errorApi'を設定し、それが呼ばれるようにしています。$this->controller->set()で出力するメッセージを定義しています。$this->_outputMessage()で出力するテンプレートを設定しています。

<?php
//app/Lib/Error/AppExceptionRenderer.php
class AppExceptionRenderer extends ExceptionRenderer {
    public function __construct(Exception $exception) {
        parent::__construct($exception);

        if ($exception instanceof ApiException) {
            $this->method = 'errorApi';
        }   
    }   

    public function errorApi($error) {
        $message = $error->getMessage();
        $this->controller->response->statusCode($error->getCode());
        $meta = array(
            'url' => $this->controller->request->here,
            'method' => $this->controller->request->method(),
        );  
        $this->controller->set([
            'meta' => $meta,
            'error' =>[-
                'message' => $message,
            ],  
            'error_exception' => $error,
            '_serialize' => ['meta', 'error']
        ]); 
        $this->_outputMessage('error_api');
    }   

}

2.app/Lib/Error/error_api.ctpを作成

<?php
//app/Lib/Error/error_api.ctp
/**
 *
 *
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       app.View.Errors
 * @since         CakePHP(tm) v 0.10.0.1076
 */
?>
<h2><?php echo h($error['message']); ?></h2>
<p class="error">
    <strong>Api Error</strong>
    <strong><?php echo h($meta['url']); ?></strong>
</p>
<?php
if (Configure::read('debug') > 0): 
        echo $this->element('exception_stack_trace', array('error' => $error_exception));
endif;
?>

3.app/Config/core.phpとapp/Config.bootstrap.phpに以下の記述を追加

ここでどのrendererを使うかの記述をします。ここではAppExceptionRendererを使う設定を記述します。

<?php
//app/Config/core.php
Configure::write('Exception', array(
    'handler' => 'ErrorHandler::handleException',
    'renderer' => 'AppExceptionRenderer',
    'log' => true
));

bootstrap.phpで自分でつくったクラスを読み込みます。

<?php
//app/Config/bootstrap.php
//初めの行に追加
App::import('Lib', 'Error/ApiException');
App::import('Lib', 'Error/AppExceptionRenderer');

こんな感じですね。CakePHPのコアファイルExceptionRenderrer.phpとexceptions.phpを読めばだいたい

参考記事1 参考記事2 を参考にしました。というより、参考記事1をそのまま使った感じですが、、

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