Gluing Ajax with the Zend Framework
As I moved forward with the implementation of the recordshelf application I wanted to use Ajax in interaction with the Zend Framework. It all started with a typical XMLHttpRequest to one of the defined methods of the customized Zend_Controller_Action objects, like in the following code snippet using the Prototype 1.5 libary.
var id = element.getAttribute('id');This all comes down to a XMLHttpRequest to the recordshelf controller and its hosted foo action by passing one parameter id and handling the response data or HTTP status error code of the called action.
new Ajax.Request('/recordshelf/foo' + id, {
method: 'post',
onSuccess: function(transport, json) {
//use and handle foo response data
},
on500: function(transport) {
//handle error, inform user
},
...
});
In the requested action of the contoller the provided functionality of the model is used, which migth return a resultset or in the worst case throw an exception, which gets translated into a HTTP status error code of 500. The data or error can be responded to the requesting client in several formats like Json, Xml or just Raw Text. Therefor a Zend_Controller_Response_Http object is build in the request handling action containing all the infomation in the specified response format for the client.
As a image is more worth than thousand words here's an UML sequence diagramm showing the flow and involved components.
The following code outlines how to build an Ajax response for the action foo of the Recordshelf_Controller using Json and Xml as response format. The used PHPDoc tag @ajaxaction is not mandatory, it's just used here to stress that foo action is handling an Ajax request and is used further for examination of the source file via the PHP Reflection API.
The following image shows the Json server response in the Firebug console.
class Recordshelf_Controller extends Zend_Controller_Action {
...
/**
* @ajaxaction
*/
public function fooAction() {
$this->_helper->viewRenderer->setNoRender();
$model = $this->getModelInstance();
/* fetch id from request, value validation omitted */
$id = $this->getRequest()->getParam('id');
/* [Json response] */
$responseData = $model->getResponseDataForClient($id);
try {
$responseDataJsonEncoded = Zend_Json::encode($responseData);
$this->getResponse()->setHeader('Content-Type', 'application/json')
->setBody($responseDataJsonEncoded);
} catch(Zend_Json_Exception $e) {
// handle and generate HTTP error code response, see below
}
/* [Xml response] */
$responseDataXmlEncoded = $model->getResponseDataForClientAsXml($id);
$this->getResponse()->setHeader('Content-Type', 'text/xml')
->setBody($responseDataXmlEncoded);
/* [HTTP error code response] */
try {
$responseData = $model->getResponseDataFailing();
...
} catch(Exception $e) {
$this->getResponse()->setHttpResponseCode(500)
->setBody('Internal Server Error');
}
}
...
}
6 comments:
What happens if a user points their browser to http://your.site.com/Recordshelf_Controller/fooAction ?
I am experimenting with ZF and AJAX and I do not know how to work around this?
Hello Ben,
The fooAction of the Recordshelf_Controller is executed by your example request. As the fooAction polls the data for the response from the model by a provided id you might add a guard clause to check for the availability of the id as a parameter in the request object.
If you want to allow only Ajax requests to the action you have to add an additional guard clause checking if the request is a Javascript XMLHttpRequest.
If the 'id is present' guard clause fails you can set a HTTP error code for the Ajax request response. In case the guard clause for the XMLHttpRequest fails you can make a redirect to an action responsible for error handling/displaying.
This is an excellent blueprint for using AJAX with the Zend framework. The UML is snazzy. Thanks.
good tutorial, it helps me very much. thanks
You missed out on the two action helpers built in ZF for this task, the context switch, and ajax context.
They weren't available three years ago, but welcome to the party ;P
Post a Comment