2012-06-20 31 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' 
    ) 
));