Category Archives: javascript

Yii and ajax error handling

Continue to write about interaction between yii and frontend.

Problem: create common solution to handle ajax errors on frontend. The main problem here is that in case of error yii will return error message as text. If you look inside CErrorHandler you’ll find such code

if($this->isAjaxRequest())
    $app->displayException($exception);
else
    $this->render('exception',$data);

if it’s ajax request we out application class will display exception. In general case it’s CWebApplication that will show you plain text with error details.

But imagine that you make some request on frontend and assuming to get JSON data. If some error happens you get error message. So you need to check somehow is it json and if it’s not json most likely it’s an error message. I’d like to get more smart solution.

Solution: let’s return for AJAX request in all cases result flag something like array(‘result’ => ‘true’, ‘data’ => array(our result data)). And then on frontend we in case of ajax error we will handle it.

So what do we need. Let’s create our own application class.

<?php

namespace Ql\Comp;

class WebApplication extends \CWebApplication
{


    public function displayException($exception)
    {
        $error = '';
        if (YII_DEBUG) {
            $error .= '<h1>' . get_class($exception) . "</h1>\n";
            $error .= '<p>' . $exception->getMessage() . ' (' . $exception->getFile() . ':' . $exception->getLine() . ')</p>';
            $error .= '<pre>' . $exception->getTraceAsString() . '</pre>';
        } else {
            $error .= '<h1>' . get_class($exception) . "</h1>\n";
            $error .= '<p>' . $exception->getMessage() . '</p>';
        }

        if ($this->getRequest()->getIsAjaxRequest()) {
            header('Content-type: application/json');
            echo \CJavaScript::jsonEncode(array(
                'result' => 0,
                'error' => $error,
            ));
        } else {
            echo $error;
        }
    }

}

And now we need to use our application class. Let’s add changes to index.php

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

As you see I don’t use default yii namespace structure. I add my own namespace and then use psr-0 autoload conventions. Nothing fancy but it will work a little bit faster. Oh and you need to add namespace to yii::app(). I added this line in config/main.php

Yii::setPathOfAlias(‘MyNamespace’, realpath(dirname(__FILE__) . ‘/../MyNamespace’));

The last trick we do for frontend.

$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
    var errorPopupHtml, result;
    result = JSON.parse(jqXHR.responseText);
    if (result.result === 0) {
      errorPopupHtml = JST['app/error']({
        title: "Error",
        error: result.error
      });
      // here I use modal popup from twitter bootstrap but you can use whatever you want.
      $(window.document.body).append(errorPopupHtml);
      return $('#myModal').modal({});
    }
  });

That’s it for today. If someone is interested I can provide instructions for ZF that will do the same job.