猫の皮を剥ぐには多くの方法がありますが、テストを簡単にするためにDRYを維持し、推奨される脂肪モデルの概念に準拠するために、ロジックをモデル。
また、クリーンアップと例外処理を分離するために、たとえば、イベント システムを利用して、クリーンアップが必要な可能性のあるモデルをリスナーとしてアタッチできるようにすることができます (クリーンアップが必要かどうかを最もよく知っている必要があります)。カスタム エラー ハンドラーは適切なイベントをディスパッチします。これにより、例外ハンドラーはアプリの内部について知る必要がなくなります。
アイデアを説明するための非常に基本的な、テストされていないコード例を次に示します。
<?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);
}
}
?>
アップデート
特定の例外のみに反応できるようにするために、たとえば、イベント名に例外クラス名を使用できます。これにより、...beforeHandleFooBarException
明示的にサブスクライブできるようなイベントがトリガーされます。
<?php
class AppErrorHandler extends ErrorHandler
{
public static function handleException(Exception $exception)
{
CakeEventManager::instance()->dispatch(new CakeEvent('AppErrorHandler.beforeHandle' . get_class($exception), get_called_class(), array($exception)));
parent::handleException($exception);
}
}
?>
<?php
class ExampleModel extends AppModel
{
public $name = 'Example';
public function __construct($id = false, $table = null, $ds = null)
{
$eventManager = CakeEventManager::instance();
$callback = array($this, 'cleanup');
$eventManager->attach($callback, 'AppErrorHandler.beforeHandleInvalidCallException');
$eventManager->attach($callback, 'AppErrorHandler.beforeHandleIncompleteCallException');
parent::__construct($id, $table, $ds);
}
public function cleanup()
{
// do some magic
}
}
?>
一般的な例外イベントに固執する場合、別のオプションは、モデル イベント リスナー コールバックで例外のタイプをチェックすることです。
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
}