Elementary introduction to using jQuery ajax and the yii framework

You are viewing revision #5 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#4)

In doing internet searches trying to learn how to incorporated ajax into web pages generated by the yii framework I noticed that there seems to be a lot of confusion. I worry that too-clever hacks will be broken in upgrades of the framework.

I am documenting the way I do it (if this is way off base then someone please give me a 'heads up'). Note I'm hard-coding the jQuery because my site is heavily javascript-based anyway.

The basic procedure is to (1) write the code that responds to (processes) the ajax call as an action in a controller and (2) call the action with the (yii-framework) appropriate url in the jQuery method. I'll call the controller AppController.php and the view will be under protected/views/app/index.php. Both are automagically created by gii.

The view (protected/views/app/index.php) is the part of the web app your users are interacting with on the page. As such, it needs to import the javascript files. This is done by 'registering' the scripts at the 'top' of the file. In our case, with scripts in a directory called 'js' just under the document root for the app, we have

<?php
/* @var $this AppController */

$this->breadcrumbs=array(
	'App',
);

// Include the client scripts
$baseUrl = Yii::app()->baseUrl; 

$cs = Yii::app()->getClientScript();
$cs->registerScriptFile($baseUrl.'/js/ajaxScript.js');
// more scripts would be added here by registering their filenames if needed
?>

(After this in the view file is the html business.)

The controller is /protected/controllers/AppController.php

In AppController.php we have an action method

public function actionAjaxProcessor(){
    $a = $_POST['ajaxData'];
    // process $a and get output $b
    // output some JSON instead of the usual text/html
    header('Content-Type: application/json; charset="UTF-8"');
    echo CJSON::encode(array('output'=>$b));
    }

Finally, ajaxScript.js has this for the ajax call:

[javascript]
 ajaxCall = function(a){
            jQuery.ajax({
                // The url must be appropriate for your configuration;
                // this works with the default config of 1.1.11
                url: 'index.php?r=app/ajaxProcessor',
                type: "POST",
                data: {ajaxData: a},  
                error: function(xhr,tStatus,e){
                    if(!xhr){
                        alert(" We have an error ");
                        alert(tStatus+"   "+e.message);
                    }else{
                        alert("else: "+e.message); // the great unknown
                    }
                    },
                success: function(resp){
                    nextThingToDo(resp);  // deal with data returned
                    }
                });
            };

The script will bind this function to a button click or other event, usually. See the jQuery website documentation (it is excellent) for more about this.

Note how we get to the controller action by using our usual controller/action url scheme in the ajax call.

This is all you need to do to modify the normal "php + ajax way" to the yii framework. I hope it saves some other newbies some time.

Why this won't (always) work

The URL of the AJAX request is relative: "index.php?r=app/ajaxProcessor". It makes 2 assumptions:

  • The page that initiates the call has an URL ending with "index.php" or its directory.
  • Yii reads the route (controller and action) through the GET parameter "r".

With a recent version of Yii, both assumptions can be wrong depending on the configuration of the application.

The solutions

You can't guess the webservice URL in pure Javascript! This URL will depend on the configuration of the application. So there are at least 2 solutions that mix in PHP and JS:

  • Make the JS file a PHP template
  • Provide JS variables from the main PHP view.