CakePHP异常逻辑

CakePHP异常逻辑,cakephp,exception-handling,Cakephp,Exception Handling,我有一个控制器,在其中抛出一个自定义异常,还有一个自定义异常呈现器类,它扩展了基本异常呈现器 现在,当我抛出异常时,我想对出错的东西进行一些清理,然后呈现一个自定义错误页面 class AppExceptionRenderer extends ExceptionRenderer { public function invalidCall($error) { $this->controller->render('/Errors/invalid_call');

我有一个控制器,在其中抛出一个自定义异常,还有一个自定义异常呈现器类,它扩展了基本异常呈现器

现在,当我抛出异常时,我想对出错的东西进行一些清理,然后呈现一个自定义错误页面

class AppExceptionRenderer extends ExceptionRenderer {

    public function invalidCall($error) {
        $this->controller->render('/Errors/invalid_call');
        $this->controller->response->send();
    }

    public function incompleteCall($error) {
        $this->controller->render('/Errors/incomplete_call');
        $this->controller->response->send();
    }
}
到目前为止,渲染效果良好。但是我应该把清理工作的逻辑放在哪里呢?
例外本身?在渲染器中?在抛出异常之前在控制器中?

嗯,通常有很多方法可以剥猫皮,但是我想说,为了留下来,为了便于测试,为了遵守,你应该把逻辑放在模型中

为了将清理和异常处理解耦,例如,您可以利用并让可能需要清理的模型将其自身作为侦听器连接(它们应该最清楚是否需要清理),并让自定义错误处理程序分派适当的事件,这样,异常处理程序就不需要知道应用程序内部的情况

下面是一些非常基本、未经测试的示例代码,可以说明这一想法:

<?php
App::uses('CakeEventManager', 'Event');

class ExampleModel extends AppModel
{
    public $name = 'Example';

    public function __construct($id = false, $table = null, $ds = null)
    {
        CakeEventManager::instance()->attach(array($this, 'cleanup'), 'AppErrorHandler.beforeHandleException');
        parent::__construct($id, $table, $ds);
    }

    public function cleanup()
    {
        // do some magic
    }
}
?>

<?php
App::uses('CakeEvent', 'Event');
App::uses('CakeEventManager', 'Event');

class AppErrorHandler extends ErrorHandler
{
    public static function handleException(Exception $exception)
    {
        CakeEventManager::instance()->dispatch(new CakeEvent('AppErrorHandler.beforeHandleException', get_called_class(), array($exception)));
        parent::handleException($exception);
    }
}
?>
如果您坚持使用通用异常事件,那么另一个选项是在models事件侦听器回调中检查异常的类型:

public function __construct($id = false, $table = null, $ds = null)
{
    CakeEventManager::instance()->attach(array($this, 'beforeHandleException'), 'AppErrorHandler.beforeHandleException', array('passParams' => true));
    parent::__construct($id, $table, $ds);
}

public function beforeHandleException($exception)
{
    if($exception instanceof InvalidCallException ||
       $exception instanceof IncompleteCallException)
    {
        $this->cleanup();
    }
}

public function cleanup()
{
    // do some magic
}

嗯,通常有很多方法可以剥猫的皮,但我想说,为了留下来,为了便于测试,为了遵守,你应该在模型中加入逻辑

为了将清理和异常处理解耦,例如,您可以利用并让可能需要清理的模型将其自身作为侦听器连接(它们应该最清楚是否需要清理),并让自定义错误处理程序分派适当的事件,这样,异常处理程序就不需要知道应用程序内部的情况

下面是一些非常基本、未经测试的示例代码,可以说明这一想法:

<?php
App::uses('CakeEventManager', 'Event');

class ExampleModel extends AppModel
{
    public $name = 'Example';

    public function __construct($id = false, $table = null, $ds = null)
    {
        CakeEventManager::instance()->attach(array($this, 'cleanup'), 'AppErrorHandler.beforeHandleException');
        parent::__construct($id, $table, $ds);
    }

    public function cleanup()
    {
        // do some magic
    }
}
?>

<?php
App::uses('CakeEvent', 'Event');
App::uses('CakeEventManager', 'Event');

class AppErrorHandler extends ErrorHandler
{
    public static function handleException(Exception $exception)
    {
        CakeEventManager::instance()->dispatch(new CakeEvent('AppErrorHandler.beforeHandleException', get_called_class(), array($exception)));
        parent::handleException($exception);
    }
}
?>
如果您坚持使用通用异常事件,那么另一个选项是在models事件侦听器回调中检查异常的类型:

public function __construct($id = false, $table = null, $ds = null)
{
    CakeEventManager::instance()->attach(array($this, 'beforeHandleException'), 'AppErrorHandler.beforeHandleException', array('passParams' => true));
    parent::__construct($id, $table, $ds);
}

public function beforeHandleException($exception)
{
    if($exception instanceof InvalidCallException ||
       $exception instanceof IncompleteCallException)
    {
        $this->cleanup();
    }
}

public function cleanup()
{
    // do some magic
}

“清理”代码到底在做什么?@ndm:从数据库中删除一些“死”项。“清理”代码到底在做什么?@ndm:从数据库中删除一些“死”项。这不会影响所有其他异常?或者我也必须为另一个编写处理程序吗?对,这个示例将触发每个异常的侦听器。如果只想绑定到特定的异常,例如,可以基于异常生成事件名称,或者可以在模型侦听器回调中测试异常的类型。我将用例子来更新我的答案,说明这一点。这不会影响所有其他例外情况吗?或者我也必须为另一个编写处理程序吗?对,这个示例将触发每个异常的侦听器。如果只想绑定到特定的异常,例如,可以基于异常生成事件名称,或者可以在模型侦听器回调中测试异常的类型。我将用例子来更新我的答案。