Difference between #3 and #2 of Elementary introduction to using jQuery ajax and the yii framework

unchanged
Title
Elementary introduction to using jQuery ajax and the yii framework
unchanged
Category
How-tos
unchanged
Tags
AJAX
changed
Content
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]
<?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




~~~
[php]
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 confi 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 are wrong with the default
configuration.

### 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.