Yii 1.1: Elementary introduction to using jQuery ajax and the yii framework

16 followers

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:

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.

Total 4 comments

#12233 report it
afser at 2013/03/08 09:33am
URL might not be the issue but DATA is !

Lets say I have configured my URLmanager as

'urlManager'=>array(
        'urlFormat'=>'path',
        'showScriptName'=>false,
        ),

So that I can make a call to

http://myapp/app/ajaxProcessor

But if I use the below code

jaxCall = function(a){
            jQuery.ajax({
                // The url must be appropriate for your configuration;
                // this works with the default config of 1.1.11
                url: 'http://myapp/app/ajaxProcessor',
                type: "POST",
                data: {ajaxData: a},

When the JS makes the AJAX POST request(or GET request) it will always make the request with a URL like :

http://myapp/app/ajaxProcessor?ajaxData=a

So if I have activated 'urlFormat'=>'path' then I will always get an AJAX error since I am not using

http://myapp/app/ajaxProcessor/ajaxData/a

To make that request.

How to make JS use the path urlFormat or what can be a solution?

#9825 report it
François Gannaz at 2012/09/13 11:04am
urlFormat

See The Definitive Guide to Yii, URL Management for an explanation. The page almost begins with a warning:

You can specify URLs without using Yii but it is not recommended since you will not be able to easily change URLs via configuration without touching application code or to achieve application portability.

But I was wrong about the default config: the config file that Yii generates by default does contain the lines

    'components' => array(
        'urlManager' => array(
            'urlFormat' => 'path',

but they are commented by default.

#9823 report it
dhimes at 2012/09/13 08:22am
Added comment to code to clarify

Hi François,

Thank you for your changes and comments. I added a comment to the code concerning the URL issue you brought up. You are correct that it shouldn't be taken as obvious that the URL used may vary with the configuration.

If you are saying, however, that with recent versions of yii this URL could change depending on how the page is loaded (or due to some other dynamic effect) then that is an entirely different story. In fact, that may make the framework a bad choice in general going forward because developers are starting to rely more on client-side processing.

So, for the record, and in order to make the wiki as clear and precise as possible, which version's default does the url I provided not work for? I started (perhaps a month ago) with version 1.1.11, and it works fine for that. If you could add to my comment where it breaks down that would be very helpful. Thank you.

#9814 report it
François Gannaz at 2012/09/12 05:20pm
Updated

I updated the article. The minor change was adding a HTTP header for JSON instead of serving it as an HTML page. Then I appended an explanation of why this method won't work: it tries to guess the URL of the AJAX service from pure JS, while this URL depends on a PHP configuration. I gave hints on how to fix this.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: dhimes
  • Updated by: François Gannaz
  • Category: How-tos
  • Yii Version: 1.1
  • Votes: +6
  • Viewed: 27,425 times
  • Created on: Sep 12, 2012
  • Last updated: Sep 13, 2012
  • Tags: AJAX