Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii: Catching all exceptions for a specific controller

Tags:

yii

I am working on a project which includes a REST API component. I have a controller dedicated to handling all of the REST API calls.

Is there any way to catch all exceptions for that specific controller so that I can take a different action for those exceptions than the rest of the application's controllers?

IE: I'd like to respond with either an XML/JSON formatted API response that contains the exception message, rather than the default system view/stack trace (which isn't really useful in an API context). Would prefer not having to wrap every method call in the controller in its own try/catch.

Thanks for any advice in advance.

like image 304
Eugene Avatar asked Jun 20 '12 20:06

Eugene


People also ask

How to display error in yii?

If you want to show an error page telling the user that his request is invalid or unexpected, you may simply throw an HTTP exception, such as yii\web\NotFoundHttpException. The error handler will correctly set the HTTP status code of the response and use an appropriate error view to display the error message.

How do I enable error reporting in yii?

1 Disable Or EnableThe Yii2 error handler is enabled by default. You can disable it by adding following code to your application entry script: YOUR_APP_FOLDER/web/index.

What is $App in yii?

Applications are objects that govern the overall structure and lifecycle of Yii application systems. Each Yii application system contains a single application object which is created in the entry script and is globally accessible through the expression \Yii::$app .

Where are yii logs?

yii\log\DbTarget: stores log messages in a database table. yii\log\EmailTarget: sends log messages to pre-specified email addresses. yii\log\FileTarget: saves log messages in files. yii\log\SyslogTarget: saves log messages to syslog by calling the PHP function syslog() .


2 Answers

You can completely bypass Yii's default error displaying mechanism by registering onError and onException event listeners.

Example:

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;
  }

  // ...
}
like image 79
medve Avatar answered Sep 23 '22 01:09

medve


I wasn't able to attach events in controller, and I did it by redefinition CWebApplication class:

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);
}
}

In index.php:

require_once(dirname(__FILE__) . '/protected/components/WebApplication.php');
Yii::createApplication('WebApplication', $config)->run();
like image 39
w4kskl Avatar answered Sep 26 '22 01:09

w4kskl