2012-06-20 16 views
16

Pracuję nad projektem, który zawiera komponent API REST. Mam kontroler dedykowany do obsługi wszystkich wywołań REST API.Yii: Łapanie wszystkich wyjątków dla określonego kontrolera

Czy istnieje sposób na wychwycenie wszystkich wyjątków dla tego konkretnego kontrolera, aby móc wykonać inne działanie dla tych wyjątków niż pozostałe kontrolery aplikacji?

IE: Chciałbym odpowiedzieć na sformatowaną odpowiedź API XML/JSON, która zawiera komunikat wyjątku, zamiast domyślnego widoku systemu/śledzenia stosu (który nie jest naprawdę użyteczny w kontekście interfejsu API). Wolałby nie zawijać wszystkich wywołań metod w kontrolerze we własnym try/catch.

Dzięki za wszelkie porady z góry.

Odpowiedz

36

Można całkowicie domyślny błąd Bypass Yii mechanizm wyświetlania rejestrując onError i onException nasłuchiwania zdarzeń.

Przykład:

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

Dzięki Próbowałem wszelkiego rodzaju rzeczy, ale rozwiązanie jest zdecydowanie najlepszym sposobem przesłonić obsługi błędu/wyjątku dla rzeczy jak kontroler interfejsu API. –

3

Możesz napisać własną funkcję actionError() na kontroler. Istnieje kilka sposobów przeprowadzenia opisanej here

9

I nie był w stanie dołączyć zdarzeń w sterowniku, a ja zrobiłem to przez klasę redefinicja 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); 
} 
} 

W index.php:

require_once(dirname(__FILE__) . '/protected/components/WebApplication.php'); 
Yii::createApplication('WebApplication', $config)->run(); 
0

Używam następującego kontrolera podstawowego dla interfejsu API, nie jest to bezpaństwowy interfejs API, ale może również służyć.

klasa BaseJSONController rozszerza 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); 
     } 
} 

Można też złapać dbException i napisz do nich, ponieważ są one nieco krytyczny i może pokazać podstawowy problem w projektowaniu kod/db.

0

Dodaj to do kontrolera:

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