Yii 1.1: Display a nice exception message on ajax requests

21 followers

Basics

When an exception is thrown in our code like

throw new CHttpException(403, 'You are not authorized to perform this action.');

if it is a CHttpException or if YII_DEBUG is not true, the error message can be displayed by using CErrorHandler::errorAction. In the default code generated by yiic this is set to SiteController::actionError() by this settings in config/main.php

'errorHandler' => array(
    'errorAction' => 'site/error',
),

But

in Yii versions previous to 1.1.9 exceptions was handled differently during ajax request and displayed by CApplication::displayException(). This way the exception message displayed on ajax requests could not be customized.
The message for the CGridView delete request with YII_DEBUG set to true looked like old exception message on ajax request

In Yii version 1.1.9 the check for ajax request has been removed so now the exception message is handled by CErrorHandler::errorAction even during ajax requests.

This way the message can be customized for ajax requests.

Example

by using this code

public function actionError()
{
    if($error=Yii::app()->errorHandler->error)
    {
        if(Yii::app()->request->isAjaxRequest)
            echo $error['message'];
        else
            $this->render('error', $error);
    }
}

the exception message for CGridView delete request will look like new exception message on ajax request

Total 3 comments

#14608 report it
darkheir at 2013/08/27 03:47pm
Another solution

In the new versions you can't do it like this since ajax request are redirected to CApplication::displayError as Stephen51 said.

My solution is to catch the exception, set an error header and then echo your message. In the next example I'm catching CDbException and check if the error is "a foreign key constraint fails" (sql error 1451). If it is I display the message, otherwise I throw back the exception:

try {
    $this->loadModel($id)->delete();
} catch (CDbException $e) {
    if($e->errorInfo[1] == 1451) {
        header("HTTP/1.0 400 Relation Restriction");
        echo "Your error message.\n";
    } else {
        throw $e;
    }
}
#14138 report it
Stephen51 at 2013/07/22 02:53pm
Added back

It looks like the change MDomba made to the code has been undone. I see on line 284 of CErrorHandler.php, there is a check for $this->isAjaxRequest() and the code is directed to CApplication::displayError().

#5190 report it
dckurushin at 2011/09/21 04:58pm
Nice tip

A good idea could be to add

else
       throw new CHttpException(400, Yii::t('err', 'bad request'));

if some one accessing error action directly...

Leave a comment

Please to leave your comment.

Write new article