A Wired.com user account lets you create, edit and comment on Webmonkey articles. You will also be able to contribute to the Wired How-To Wiki and comment on news stories at Wired.com.
It's fast and free.
processing...Retrieve Sign In
Please enter your e-mail address or username below. Your username and password will be sent to the e-mail address you provided us.
processing...Welcome to Webmonkey
- edit articles
- add to the code library
- design and write a tutorial
- comment on any Webmonkey article
Sign In Information Sent
Ajax Controller
/skill level/
/viewed/
Contents |
Introduction
Ajax Controller, This controllers will handle all the data transfers between the server and the frontend.
Having a single function to contact the serverside to retrieve the response, helps to keep your projects simple and maintanable.
So no 15 scripts to sends your Ajax requests to, just 1 script that handles all the serverside actions for you and one script to handle all the frontend handling.
What you'll need
PHP or any serverside language
Javascript expertise, I made the controller with the Prototype library, but I also made the same controllers with Mootools and jQuery so no worries if you`re a jQuery of Mootools man/woman. (if you want the jQuery of Mootools version just let me know)
Code and Explanation
First the Javascript ARRM Controller (Ajax Result Request Manager):
var ARRM = Class.create({
initialize: function(url){
this.url = url;
},
encodeObjectValues: function(obj){
for (key in obj) {
if (typeof(obj[key]) == "object") {
obj[key] = this.encodeObjectValues(obj[key]);
}
else {
obj[key] = encodeURIComponent(obj[key].toString().split("\"").join("\\\""));
}
}
return obj;
},
jsonRequest: function(params, func){
data = "json=" + Object.toJSON(this.encodeObjectValues(params));
new Ajax.Request(this.url, {
method: 'post',
postBody: data,
onComplete: function(transport){
var data = transport.responseText.evalJSON(true);
func(data);
}
});
}
});
var ARRM = new ARRM('/locationToAjaxAontroller/AjaxController.php');
Above is the javascript ajax Controller, to create a new instance of the controller insert the code below in your script (try to do it after the dom is loaded). After this you can use the ARRM variable in all you scripts to feed it with data.
var ARRM = new ARRM('/locationToAjaxAontroller/AjaxController.php');
Below we see a new javascript object sending a request to ARRM.jsonRequest. The function AjaxCheck() will fire a new request to ARRM. To do this you create a new object. You will supply the object with a newType and a newMethod these variables are the Class on the server and the function inside that class that you will be using to handle you request.
In this case were sending the request to the Class => AjaxTest and using the TestAjax function. For now were keeping it basic so no additional variables are needed.
the function jsonRequest: function(params, func) accepts a func variable, this func variable is the function you want to be called when the server returns it response.
var AjaxCheck = Class.create({
initialize: function(){
this.AjaxCheck();
},
AjaxCheck: function(){
func = this.AjaxCheckFeedback.bind(this);
var obj = {};
obj.newType = 'AjaxTest';
obj.newMethod = 'TestAjax';
ARRM.jsonRequest(obj, func);
},
AjaxCheckFeedback: function(obj){
alert(obj.response);
}
});
The ARRM.jsonRequest fires a request to the ARRM and the ARRM send its request to the serverside. (AjaxController.php) it send the func = this.AjaxCheckFeedback.bind(this); with the request, this is the function you want the ARRM to execute after the response came back from the server.
Then now the serverside: AjaxController.php
Below is the AjaxController class that we need to enter our backend.
For now the AjaxController accepts JSON, but you can modify it to your needs
class AjaxController
{
private $postVars;
public function __construct($obj)
{
/**
* decode the posted JSON vars
*/
$this->postVars = json_decode(stripslashes($obj), false);
/**
* construct AjaxAppLoader to retrieve all the objects
*/
$this -> ajaxRequest($this->postVars);
}
/**
* retrieve the newMethod function on the newType object
* @return Object
* @param $obj Object
*/
private function getResult( stdClass $obj)
{
return $this->{$obj->newType}->{$obj->newMethod}($obj);
}
/**
* json_encode the result of getResult and return to javascript
* @return Object
*/
public function ajaxRequest()
{
return json_encode($this->getResult($this->postVars));
}
}
/**
* strip the slashes for errors in decoding
*/
foreach ($_POST as $key=>$value)
{
$_POST[$key] = stripslashes($value);
}
new AjaxController($_POST['json']);
Above is the AjaxController Class, it converts the JSON format request to
a readable format for PHP. It then feeds the variables to ajaxRequest(). This function calls getResult() and within that function the newType and newMethod that were send from ARRM, are converted to a new Class and calls its function that we want.
Ok to get the Controller to create a new Class on the fly without including them all in the top of your page you can use the __autoload function from PHP. If you include the functions below in the top of your page, PHP will look for the Classes in the predefined directories until it finds the file with the Classname in it and creates a new Class instance of it for you to acces.(change the pre defined vars to your location where you keep your class files)
/**
* __autoload()
*
* PHP magic function
* loads the classfiles with the supported classname
*
* @return
* @param $className Object
*/
function __autoload($className)
{
getFromDir(SITE_ROOT.SITE_CLASSES, $className);
}
/**
* getFromDir()
*
* grabs the files with the supported classname and the Class.class.php format
*
* @param $dir Object
* @param $classFile Object
*/
function getFromDir($dir, $classFile)
{
if (is_file($dir.'/'.$classFile.'.class.php'))
{
require_once ($dir.'/'.$classFile.'.class.php');
} elseif ($handle = opendir($dir))
{
while (false !== ($file = readdir($handle)))
{
if ($file != "." && $file != "..")
{
if (is_dir($dir."/".$file))
{
getFromDir($dir."/".$file, $classFile);
}
}
}
}
}
Ok back to the AjaxController, after it created the Class instance and has called its function it retrieves the data from that function and returns it to the frontend.
Ok lets take a quick peek at the Class instance were creating and the function were calling to see what data were receiving and returning.
class AjaxTest
{
public function __construct($obj)
{
}
public function TestAjax($obj)
{
$obj = new stdClass();
$obj - > response = "Ajax functionality works!";
return $obj;
}
}
We create a new object and create the response property and fill it with a string. Then we return it to the AjaxController.
Back at the AjaxController, Before we can return it to the frontend, we encode the object we are going to send, to the JSON format so that the ARRM knows what to do with it and make it possible to feed it to the func
return json_encode($this->getResult($this->postVars));
The AjaxController returns it to the ARRM and is received by the
onComplete: function(transport){
var data = transport.responseText.evalJSON(true);
func(data);
}
Here it is evaluated as a JSON object and fed to the func which has been predefined by us earlier on. The function we specified retrieves the object and alerts the result.
AjaxCheckFeedback: function(obj){
alert(obj.response);
}
Thats it!!! Now you can use Ajax in a more structured way and mantain all your Ajax request from one server file and one frontend function.
For any questions just let me know, if you want the Mootools or the jQuery version let me know as well and ill post or send them to you.
Suggested readings
visit the PrototypeJs site [1]
- This page was last modified 22:43, 20 May 2008.
/related_articles/
Special Offer For Webmonkey Users
WIRED magazine:
The first word on how technology is changing our world.
