2012-06-20 28 views
16

我正在处理包含REST API组件的项目。我有一个专门处理所有REST API调用的控制器。Yii:捕获特定控制器的所有例外

是否有任何方法可以捕获该特定控制器的所有异常,以便对这些异常采取与应用程序其他控制器不同的操作?

IE:我想用包含异常消息的XML/JSON格式的API响应而不是默认系统视图/堆栈跟踪(在API上下文中并不真正有用)作出响应。宁愿不必将自己的try/catch中的每个方法调用都包含在控制器中。

感谢您的任何建议提前。

回答

36

您可以完全绕过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; 
    } 

    // ... 
} 
+0

谢谢,我已经尝试了所有种类的事情,但你的解决方案是迄今为止覆盖的东西像API控制器错误/异常处理程序的最佳途径。 –

3

您可以为每个控制器编写自己的actionError()函数。有这样做的是通过注册的onErroronException的事件侦听器描述here

9

我无法连接事件控制器,我通过重新定义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(); 
0

我正在使用以下基本控制器的API,它不是无状态的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和电子邮件的,因为他们是有点严格,可以在代码/ DB设计表明潜在的问题。

0

添加到您的控制器:

Yii::app()->setComponents(array(
    'errorHandler'=>array(
     'errorAction'=>'error/error' 
    ) 
));