William Graham’s blog

August 6, 2007

Ajax 101: A Simple Example of Using Ajax with the Zend Framework

Filed under: Ajax,PHP,Programming,Web Development,Zend Framework — liamgraham @ 6:14 pm

NOTE: I’ve updated this tutorial for version 1.5 of Zend Framework. At some point after I originally wrote this, the Zend Framework team removed a loophole that I and apparently many others mistakenly relied on, relating to resolution of action names. In the original version of this tutorial, I had the javascript making an Ajax call to ‘index/getData’, which was resolving to the getDataAction method in the index controller. However, as of version 1.5 of the framework, the case is not getting preserved, so that my ‘getData‘ was getting converted to lowercase ‘getdata‘, resulting in the error that Ernesto commented about way back in February:

Fatal error: Uncaught exception ‘Zend_Controller_Action_Exception’ with message ‘IndexController::getdataAction() does not exist and was not trapped in __call()’

Basically, what needs to happen is that there needs to be a word separator in the action name in the javascript so that the framework really knows how to camelcase it, such as ‘index/get-data’. I have edited the blog post and the zipped code to correct this. For an in-depth discussion of this issue, and the team’s reasoning for blocking the loophole, see the manual here: http://framework.zend.com/manual/en/zend.controller.migration.html

Sorry for any problems people have been seeing!

-william

——————————————————————

I recently needed to port some existing php code which used Ajax over to the Zend Framework. While there are several tutorials out there with lots of details, I didn’t find a simple example that would just get me started with how to work Ajax calls into the MVC framework architecture. Eventually, I figured things out by referring to several different tutorials and doing a good amount of Googling. I decided it might be useful to have a very simple example of porting an existing Ajax app to the Zend Framework.

Warning: this app is very simplistic … it is solely designed to show minimum ‘hello world’ type of Ajax functionality, and how to fit that into the Zend Framework. There are plenty of more advanced tutorials out there, but this can get you started and show you how to make an Ajax call and respond to it with a Zend controller action. To simplify things even further, I’m using the prototype Javascript library, which makes life a lot easier by, among other things, providing a cross-browser means of creating and sending Ajax requests.

Versions: I wrote this against Prototype 1.5.1.1 and Zend Framework 1.0.1 (now updated for ZF v. 1.5)

Assumptions: I assume this is running on Apache, as I will include some .htaccess files to deal with url rewriting in the Zend version. I assume you’re familiar with Ajax … if not, there are tons of tutorials out there available via Google. I also assume you have some basic familiarity with the Zend Framework. If not, I recommend Rob Allen’s great introductory tutorial. And if you need to run the tutorial on Oracle instead of Mysql, well, of course, I recommend this blog post … 😉

If you want the code, download the zip file, which contains both the Zend app (ajax101_zend directory) and the non-Zend app (ajax101 directory). Both directories also contain the version of prototype that I used. Earlier versions of the download also contained Zend Framework v1.0.1, but I removed this at the same time I updated the code to work with ZF v1.5. I wrote the code on Windows, so be aware of that if you have any problems with the files on other platforms …

Okay, on to the code. First, the non-Zend version. I created three files (index.html, boxy.css, and server_script.php) and put them in the same directory on my webserver, along with the prototype.js file. Here’s the index.html, with a couple of Javascript functions to handle the Ajax call and response (we’ll factor those out to a separate file in the Zend version):

————————————————————————————

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<html>
<head>
<title>Ajax 101</title>
<link rel=”stylesheet” href=”boxy.css”>
<script type=”text/javascript” src=”prototype.js”></script>

<script language=’javascript’>

//handle the Ajax response …
function handleResponse(transport)
{
$(‘hello’).innerHTML = transport.responseText;
}

//creates a prototype Ajax object, sends a request, and registers the callback function ‘handleResponse’
function callAjax(s)
{
var myAjax = new Ajax.Request(‘server_script.php’,
{method: ‘get’, parameters: {state: s},
onComplete: handleResponse});
}

</script>

</head>
<body>
<p>
<span id=’hover_span’ onmouseover=”callAjax(‘do’)” onmouseout=”callAjax(‘undo’)”> <b>Hover here to trigger Ajax call:</b> </span>
</p>

<span id=’hello’> boring pre-Ajax-call text … </span>

</body>
</html>

————————————————————————————

Here’s the simple stylesheet used:

————————————————————————————

#hover_span
{
font-size: 12pt;
}

#hover_span:hover
{
cursor: crosshair;
background-color: yellow;
}

————————————————————————————

And here is the php server-side script which simply echoes some text back depending on the ‘state’ parameter passed in the request:

————————————————————————————

<?php

$state = $_REQUEST[‘state’];

if ($state == ‘do’)
{
echo ‘<h1>exciting text retrieved from server!</h1>’;
}
else if ($state == ‘undo’)
{
echo ‘reset to boring …’;
}
else
{
echo ‘unknown state parameter passed to server!!’;
}

————————————————————————————

So, if you trace through what happens, when you hover over the text at the top of the index.html page, Hover here to trigger Ajax call, the mouseover event fires, sending an Ajax request with a ‘state’ parameter of ‘do’ to the server. The server responds with the text exciting text retrieved from server! enclosed in h1 tags. When the mouse leaves the text at the top of the page, the mouseout event fires, sending an Ajax request with a ‘state’ parameter of ‘undo’ to the server, which responds with the text reset to boring …

Pretty simple, nothing exciting or difficult … just a super-basic example of doing something with Ajax. Okay, so how do we move that into the Zend Framework?

The first thing that is going to change is the directory structure. As I mentioned, for the simple ‘Ajax 101’ app, I just put all the files in the same directory on my webserver. For Zend, I’m going to need to separate things out, which is a good thing. I’m following a typical Zend Framework directory structure here, so it will look like this:

docroot
–app
—-controllers
—-views
——scripts
–library
–public
—-scripts
—-styles

You may have noticed the lack of a model directory. That’s because in this very simplistic example, there are no models.

Okay, so what next? Well, first we need to install the framework. Download the latest version of the framework (I used v1.5.1 in the latest work I did on this). Once you’ve extracted it, copy the library/Zend directory to your docroot/library directory.

Next we need a bootstrap file for the framework. This will be pretty simple for this example, since we’re not doing much, so we won’t be loading a bunch of Zend classes, setting up database connections, etc. All we’ll really be doing is some basic settings, like error reporting, include paths, and setting up the controller. This is in the index.php file in the docroot:

————————————————————————————

<?php

error_reporting(E_ALL | E_STRICT);
date_default_timezone_set(‘America/Chicago’);

set_include_path(‘.’ . PATH_SEPARATOR . ‘./library’ . PATH_SEPARATOR . get_include_path());

include “Zend/Loader.php”;

//setup controller
Zend_Loader::loadClass(‘Zend_Controller_Front’);
$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setControllerDirectory(‘./app/controllers’);

//run
$frontController->dispatch();

————————————————————————————

Next we’ll set up a simple controller, and put the code that was in the server_script.php file inside a controller action. This is the IndexController.php file in the docroot/app/controllers directory:

————————————————————————————

<?php

class IndexController extends Zend_Controller_Action
{
function init()
{
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
Zend_Loader::loadClass(‘Zend_Debug’);
}

function indexAction()
{
//echo “<p>in IndexController::indexAction()</p>”;
$this->view->title = “Zend Ajax 101”;
}

function getDataAction()
{
$this->_helper->viewRenderer->setNoRender();

$state = $_REQUEST[‘state’];

if ($state == ‘do’)
{
echo ‘<h1>exciting text retrieved from server!</h1>’;
}
else if ($state == ‘undo’)
{
echo ‘reset to boring …’;
}
else
{
echo ‘unknown state parameter passed to server!!’;
}
}
}

————————————————————————————

The only difference between our initial php script and the code in the getDataAction() method is the crucial first line:

$this->_helper->viewRenderer->setNoRender();

This tells Zend that this particular action method is not going to result in the re-rendering of the view.

Next, here’s our index.phtml, which is just slightly altered from the index.html of the non-Zend app, and is saved in the docroot/app/views/scripts/index directory:

————————————————————————————

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<html>
<head>
<title><?php echo $this->title ?></title>
<link rel=”stylesheet” href=”public/styles/boxy.css”>
<script type=”text/javascript” src=”public/scripts/prototype.js”></script>
<script type=”text/javascript” src=”public/scripts/ajax_funcs.js”></script>

</head>
<body>
<p>
<span id=’hover_span’ onmouseover=”callAjax(‘do’)” onmouseout=”callAjax(‘undo’)”> <b>Hover here to trigger Ajax call:</b> </span>
</p>

<span id=’hello’> boring pre-Ajax-call text … </span>

</body>
</html>

————————————————————————————

You’ll notice that we’ve factored the javascript functions out to a separate file, as I said we would do. Here is that file, docroot/public/scripts/ajax_funcs.js:

————————————————————————————

//handle the Ajax response …
function handleResponse(transport)
{
$(‘hello’).innerHTML = transport.responseText;
}

//creates a prototype Ajax object, sends a request, and registers the callback function ‘handleResponse’
function callAjax(s)
{

//remember to put a word separator between elements of the camelcase action name, per the ZF manual:
var myAjax = new Ajax.Request(‘index/get-data’,
{method: ‘get’, parameters: {state: s},
onComplete: handleResponse});
}

————————————————————————————

The stylesheet is the same as the previous app, so I won’t repeat it here. Just note that it is saved in docroot/public/styles.

Finally, there are some .htaccess files we’ll need, since we need to handle rewrite rules and exceptions. In the docroot, here’s what you need in your .htaccess:

————————————————————————————

RewriteEngine on
RewriteCond %{REQUEST_URI} !/public.*

RewriteRule .* index.php

php_flag magic_quotes_gpc off
php_flag register_globals off

————————————————————————————

And for the docroot/public directory:

————————————————————————————

RewriteEngine off

————————————————————————————

Okay, that’s it! If all has gone well, you should see the same behavior in the Zend Framework version as you did in the non-Zend one. Hopefully, this will give you a jumping off point for more advanced Ajax work with the Zend Framework.

31 Comments

  1. Hi, this example is great but .. unfortunately I had a problem with IE, it shows “iexplore.exe has detected a problem and must be closed”. With Firefox everything is working.
    Any suggestions ?? :-/

    Comment by elisa — August 10, 2007 @ 10:15 pm

  2. Hi, elisa,

    Hmm … I don’t have that problem with IE … what version of IE, and what version of Windows are you running?

    I did note that my stylesheet isn’t working correctly in IE, so I’ll revisit that also. Let me know any further details, and I’ll try to help you get this running in your environment …

    Thanks!
    William

    Comment by liamgraham — August 10, 2007 @ 11:57 pm

  3. Hi !! This example finally worked on IE!! the problem was the prototype.js library. I had to use another (XHConn.js) that I founded on the web, and I also modified a little bit de code.

    I’m using Windows XP, IE 6.0.29. On Firefox everything worked just like it is.
    Thanks for your answer.

    Comment by elisa — August 13, 2007 @ 7:00 pm

  4. I’m glad it’s working for you! The strange thing is that I’m also using Windows XP and IE 6.0.29, and I don’t see the same problem you did! The only issue I have is that the stylesheet doesn’t work the same as for Firefox (big surprise, huh?) …

    But I’m very glad it works for you now!

    Comment by liamgraham — August 13, 2007 @ 7:10 pm

  5. Hi, sorry, but it doesn’t work when i wanna use it in another folder.

    I put it in test, instead of index, i have created de TestControler, and included the files correctly, but it replace the with all the html code of the index.phtml in test folder.

    I hope you can help me.
    Thanks

    Comment by binary — September 9, 2007 @ 11:11 pm

  6. Don’t know why but i change
    var myAjax = new Ajax.Request(‘index/getData’,
    for
    var myAjax = new Ajax.Request(‘getData’,

    and its work just fine.
    thanks

    Comment by binary — September 9, 2007 @ 11:25 pm

  7. Hey..
    Thx for this great tut. It worked fine, but when I upgraded my zf-library to zf_1.0.2 it does not work any more. I think its something with viewRenderer->setNoRender();.
    TNX again

    Comment by Aras — October 10, 2007 @ 11:37 am

  8. Hmmm … I’ve upgraded to 1.0.2 and have no problems. Not sure what’s going on for you, Aras? But sorry you’re having problems.

    Comment by liamgraham — November 12, 2007 @ 9:37 pm

  9. Thanks for the tutorial. I’m trying your example now, but just looking at it at don’t think there should be any problem. I’m got some understanding of all that MVC stuff using CakePHP. And I wanted a way to use ajax with Zend the way it is integrated in CakePHP.

    Comment by kanian77 — November 14, 2007 @ 8:36 pm

  10. […] működést lett volna hivatott bemutatni. Egészen addig amíg bele nem botlottam William Graham Ajax 101: A Simple Example of Using Ajax with the Zend Framework című írásába. Ezen a példán dolgozgattam, gyurmázgattam egy kicsit az alábbi […]

    Pingback by vbali blogja »  Ajax és a Zend Framework — December 28, 2007 @ 10:36 pm

  11. Very nice tutorial William. I totally agree – it’s hard to find could ZendFramework/AJAX examples. This one is excellent.

    Comment by Callan — February 13, 2008 @ 5:46 am

  12. I am getting the following error, can you please help?

    Fatal error: Uncaught exception ‘Zend_Controller_Action_Exception’ with message ‘IndexController::getdataAction() does not exist and was not trapped in __call()’

    Comment by Ernesto — February 17, 2008 @ 4:48 am

  13. Yeah good tutorial. Hey Aras try to upgrade to 1.0.3. It worked for me!

    Comment by DarkLight — February 23, 2008 @ 9:34 am

  14. Really useful. Exactly what I was looking for to keep on building my web application. Thank you so much!

    Comment by Toni M. — March 3, 2008 @ 1:05 pm

  15. Ernesto, sorry this has taken me a couple of months to get around to, but I’ve fixed the problem you were seeing. It was related to a loophole in naming conventions that the framework team closed as of version 1.5. See the note above, at the top of the article. Code in the article and in the downloadable zip file has been fixed.

    -william

    Comment by liamgraham — April 15, 2008 @ 3:37 pm

  16. […] Originally Posted by intregus bumped, as I would like some answers regarding this as well I just found this: Ajax 101: A Simple Example of Using Ajax with the Zend Framework William Graham’s blog […]

    Pingback by zend + ajax - Zend Framework Forum — April 18, 2008 @ 1:05 am

  17. I’m trying to download the example code for a few days now, but the link (http://www.geocities.com/wwgtsc/ajax101.zip) does not work. Would that be possible to put it up somewhere else?
    Thanks,
    monika

    Comment by teleki — July 14, 2008 @ 5:18 pm

  18. I have a problem
    In the non zend version,I copied the contents as mentioned in the site . I have created the folder structure properly. But its not working for me. Its not throwing any error but its not calling the server side script.
    the code I am using is
    var myAjax = new Ajax.Request(‘server_script.php’,’….’);

    Please help me .Thanks in advance

    Comment by shah — July 15, 2008 @ 7:05 am

  19. Hello,
    The link to download the code not work. How I can download it ? Thanks

    Comment by Stefano — July 30, 2008 @ 6:45 am

  20. Hello, Thaks for this tutorial, the link to download the code not work ! Can you give me a link to download your tutorial source code ! Thanks

    Comment by Steve — August 10, 2008 @ 5:36 pm

  21. Hi William I’m have some problems to use AjAX with the zend framework and i’m trying to download your example (zip file) can you send me it by email, please? Your article is very good and i would want to check you example and solve mi issue.
    Thanks

    Comment by Olaf Arias — August 21, 2008 @ 5:28 pm

  22. Good article

    Keep it up..

    Comment by M Zahid — September 8, 2008 @ 3:24 am

  23. Hi,sorry to say but its not working for me.I have a problem with alling that ajax function its gives a javascript error as “Ajax is not defined” on line “var myAjax = new Ajax.Request(’/index/ge…{state: s},onComplete: handleResponse});” in ajax_funcs.js file. I think this error is on mouseover.

    Another error is also there as “Components is not defined” on the same line.

    Please help how do i call this function without any error and can retrieve data from the getData Action.

    Comment by Abhishek — September 12, 2008 @ 1:07 pm

  24. it gives a javascript error as “Ajax is not defined” on line “var myAjax = new Ajax.Request(’/index/ge…{state: s},onComplete: handleResponse});” in ajax_funcs.js file.I think this error is on mouseover.

    Another error is also there as “Components is not defined” on the same line.

    Please help how do i call this function without any error and can retrieve data from the getData Action.

    Comment by Abhishek Kushwaha — September 12, 2008 @ 1:08 pm

  25. Hi william, I analysed the code once again and concluded that the error might occured due to absence of “prototype.js”.I do not find “prototype.js” file anywhere on your tutorial.
    The link u have given for download is also not working.
    Helip me to solve this problem as soon as possible.

    Comment by Abhishek Kushwaha — September 12, 2008 @ 1:12 pm

  26. How can you not find the prototype.js mentioned in my tutorial? It’s mentioned in the second paragraph of the tutorial, including a link to the Prototype site, and is also included in the index.phtml file.

    Sorry to everyone who is having trouble downloading the code … it’s a hosting issue that I’ve been struggling with for a while now. It should be solved soon.

    Comment by liamgraham — September 16, 2008 @ 4:40 pm

  27. The zip file with the code should be available for download now. Sorry for the hassle!!!

    Comment by liamgraham — September 18, 2008 @ 6:03 pm

  28. Hi, I am trying to use your code, however when i alert the transport.responseText is content the whole html . body etc.
    It suppose to be content only the div/span area only.
    below is my code:
    inside

    function getDataAction()
    {
    $this->_helper->viewRenderer->setNoRender();
    php process ……
    echo $content; //( this content html table block)
    }
    and when page is displayed the whole html page is repeat, can anyone tell us why its happen.

    if I am using without the function getDataAction() and calling seperate .php file its working fine.

    Thanks
    Johny

    Comment by Johny — January 2, 2009 @ 1:48 pm

  29. Hi, I found the problem but i don’t what will be the solution, the issue is because of Zend_Layout::startMvc(array(‘layoutPath’=>’../application/layouts’));
    this , it return the whole html layout.

    Comment by Johny — January 2, 2009 @ 2:03 pm

  30. Thanks. Good work. i am using IE latest version, and FF latest version. The style is not working on IE. In ff everything is good.

    Comment by Iyngaran — January 16, 2009 @ 5:27 am

  31. Thanks for the tutorial. Very helpful. Did not work well for me at the beginning, instead of outputting just the action’s returned data, it returned the whole html output… until I realized that this was because I was using Zend_Layout. If you are using it, you need to disable it for the specific action you are using.
    use:
    $this->_helper->layout()->disableLayout();

    Comment by Regis — February 5, 2009 @ 7:13 pm


RSS feed for comments on this post.

Create a free website or blog at WordPress.com.