我正在开发一个包含 REST API 组件的项目。我有一个专用于处理所有 REST API 调用的控制器。
有没有办法捕获该特定控制器的所有异常,以便我可以对这些异常采取与应用程序的其余控制器不同的操作?
IE:我想使用包含异常消息的 XML/JSON 格式的 API 响应来响应,而不是默认的系统视图/堆栈跟踪(这在 API 上下文中并不是很有用)。宁愿不必将控制器中的每个方法调用都包装在自己的 try/catch 中。
感谢您提前提供任何建议。
我正在开发一个包含 REST API 组件的项目。我有一个专用于处理所有 REST API 调用的控制器。
有没有办法捕获该特定控制器的所有异常,以便我可以对这些异常采取与应用程序的其余控制器不同的操作?
IE:我想使用包含异常消息的 XML/JSON 格式的 API 响应来响应,而不是默认的系统视图/堆栈跟踪(这在 API 上下文中并不是很有用)。宁愿不必将控制器中的每个方法调用都包装在自己的 try/catch 中。
感谢您提前提供任何建议。
通过注册onError和onException事件监听器,你可以完全绕过 Yii 的默认错误显示机制。
例子:
class ApiController extends CController
{
public function init()
{
parent::init();
Yii::app()->attachEventHandler('onError',array($this,'handleError'));
Yii::app()->attachEventHandler('onException',array($this,'handleError'));
}
public function handleError(CEvent $event)
{
if ($event instanceof CExceptionEvent)
{
// handle exception
// ...
}
elseif($event instanceof CErrorEvent)
{
// handle error
// ...
}
$event->handled = TRUE;
}
// ...
}
我无法在控制器中附加事件,我通过重新定义 CWebApplication 类来做到这一点:
class WebApplication extends CWebApplication
{
protected function init()
{
parent::init();
Yii::app()->attachEventHandler('onError',array($this, 'handleApiError'));
Yii::app()->attachEventHandler('onException',array($this, 'handleApiError'));
}
/**
* Error handler
* @param CEvent $event
*/
public function handleApiError(CEvent $event)
{
$statusCode = 500;
if($event instanceof CExceptionEvent)
{
$statusCode = $event->exception->statusCode;
$body = array(
'code' => $event->exception->getCode(),
'message' => $event->exception->getMessage(),
'file' => YII_DEBUG ? $event->exception->getFile() : '*',
'line' => YII_DEBUG ? $event->exception->getLine() : '*'
);
}
else
{
$body = array(
'code' => $event->code,
'message' => $event->message,
'file' => YII_DEBUG ? $event->file : '*',
'line' => YII_DEBUG ? $event->line : '*'
);
}
$event->handled = true;
ApiHelper::instance()->sendResponse($statusCode, $body);
}
}
在 index.php 中:
require_once(dirname(__FILE__) . '/protected/components/WebApplication.php');
Yii::createApplication('WebApplication', $config)->run();
您可以为每个控制器编写自己的 actionError() 函数。有几种方法可以做到这里描述
我正在为 API 使用以下 Base 控制器,请注意,它不是无状态 API,但它也可以提供服务。
类 BaseJSONController 扩展 CController{
public $data = array();
public $layout;
public function filters()
{
return array('mainLoop');
}
/**
* it all starts here
* @param unknown_type $filterChain
*/
public function filterMainLoop($filterChain){
$this->data['Success'] = true;
$this->data['ReturnMessage'] = "";
$this->data['ReturnCode'] = 0;
try{
$filterChain->run();
}catch (Exception $e){
$this->data['Success'] = false;
$this->data['ReturnMessage'] = $e->getMessage();
$this->data['ReturnCode'] = $e->getCode();
}
echo json_encode($this->data);
}
}
您还可以捕获 dbException 并通过电子邮件发送它们,因为它们有些关键,并且可以显示代码/数据库设计中的潜在问题。
将此添加到您的控制器:
Yii::app()->setComponents(array(
'errorHandler'=>array(
'errorAction'=>'error/error'
)
));