Writing Your Server-Side Ajax Handler

[[innerindex]]In my recent post on ‘Ajax; Templating; and the Separation of Layout and Logic,’ I refer to an Ajax Handler that sits server side to handle Ajax calls. Some elaboration is in order.

As I have stated in the past, I’m a huge fan of Prototype AND I choose PHP as my language of choice…so my examples will be using both, but the idea is portable.

Set up your Functions

Before you create a handler, you need a set of functions that the handler can reference. Here’s an example:

< ?php
function world($params='')
{
  return 'Goodbye Cruel World.';
}//end world

function sweetWorldAction($params='')
{
  //we expect params to be an array or a string similar to a parameter string from a GET..i.e. "bork=asdf&cheese=yes please"
  //parse out the variables
  if(!is_array($params))
  {
    parse_str($params,$params);
  }//end if

  //do your logic here
}//end sweetWorldAction
?>

Now that we have the functions all set, we’ll set up a handler that receives Ajax calls and calls the appropriate functions.

The Eval Method – A Dynamic Handler

This method is one that I toyed around with for a while and I’ll admit that its pretty simple and clean but there are some drawbacks. We’re going to make a few assumptions: All requests will be GET (this is to keep things simple for this example) and we will keep the complexity of .htaccess sweetness out of these examples and assume that each call will be passing a function variable that specifies the function we are calling. I’ll get to those in a second…but first I’ll show you the handler code in this Eval Method:

< ?php
//if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
ignore_user_abort();

include('functions.php');

//list out your Ajax accessible functions
$valid_functions = array('world','sweetWorldAction');

if($_GET&#91;'function'&#93; && in_array($_GET&#91;'function'&#93;,$valid_functions))
{
  //get the get parameters
  $params = $_GET;  
  //unset the function index from the params because we just don't need it there
  unset($params&#91;'function'&#93;);

  //build your parameter string:
  $param_string='';
  foreach($params as $key=>$param)
  {
    $param_string.=(($param_string)?'&':'').$key.'='.$param;
  }//end foreach

  //make your function call
  eval($_GET['function']."('$param_string');");
}//end if

?>

The Variable Variable Method – A Dynamic Handler

This method (compliments of PHPDeveloper) is simpler than the Eval Method and just as dynamic.

< ?php
//if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
ignore_user_abort();

include('functions.php');

//list out your Ajax accessible functions
$valid_functions = array('world','sweetWorldAction');

if($_GET&#91;'function'&#93; && in_array($_GET&#91;'function'&#93;,$valid_functions))
{
  //get the get parameters
  $params = $_GET;  
  //unset the function index from the params because we just don't need it there
  unset($params&#91;'function'&#93;);
  //make your function call
  $_GET&#91;'function'&#93;($params);
}//end if

?>

The Switch Method – A Basic Handler

This method handles each call individually. The reason for using switch rather than if-elses is simply because your application will most likely possess a large number of Ajax-ified functions and those if-elses would be ghastly to read and decrease performance…the Switch statement is much cleaner.

< ?php
//if the user leaves the page or closes the browser prematurely, this will help prevent half completed statements
ignore_user_abort();

include('functions.php');

if($_GET&#91;'function'&#93;)
{
  switch $_GET&#91;'function'&#93;
  {
    case 'world':
      echo world();
      exit;
    break;
    case 'sweetWorldAction':
      echo sweetWorldAction();
      exit;
    break;
  }//end switch
}//end if

?>

Make a Choice

Which are you going to use? While the Eval and Variable Variable Methods contain very small amounts of code in the handlers, the logic has simply been shifted to the functions themselves. Increased Ajax-geared logic within the functions themselves reduces portability. However, in the Switch Method, logic is organized in a fairly easy to follow manner while making use of very generic functions that can be used in multiple fashions. Obviously, the Switch Method is my preferred choice :)

In Closing

Handler scripts make the Ajax magic happen and the separation of handler logic from your application logic is just as important for robust development and debugging as the need for separation of layout and logic. Play around with the above methods and see which works for you. If you have a method all your own, I’d be interested to hear it!


Comments

19 responses to “Writing Your Server-Side Ajax Handler”

  1. Another reason to use switch over if/else is performance. Switch statements are highly optimized for a lot of conditions.

  2. grr….it apparently interpreted the PHP from the las one, so here it is again:

    If you didn’t want to use eval (remember, eval’s only one letter away from evil), you can always use variable variables:

    [php]
    function test($parms){
    print_r($parms);
    }

    //be sure to filter the input first!
    $filtered=filterThisInput($_GET);

    $filtered[‘function_called’]($filtered);
    [php]

    calling the page with: page.php?function_called=test&foo=1&bar=2
    would result in:

    Array (
    [function_called] => test
    [foo] => 1
    [bar] => 2
    )

  3. @enygma

    Yeah, good point on the eval is one letter away from evil :) Variable variables for the win!

  4. Matt, you should check out the my-BIC php/ajax framework. There is one server file mybic_server.php that pretty much does what you’re looking for, it also supports GET/POST JSON/TEXT/XML request/responses in less than 100 lines of code.
    http://www.litfuel.net/mybic

  5. I think one function for all ajax requests is not a very good idea. First, you have to invent those methods (btw, I always use ‘switch’ if I have to create something like that, my non-ajaxed blog-engine for instance), second this makes your script a bit more complicated. However, maybe, it`s just a question of style.

    I prefer another way: for each request I make file, which name consits of ‘xhr’ prefix and the name of the ajax function that ewokes it. So, for the javascript function loadCommentsData with xmlhttprequest inside, I create ‘xhr.loadCommentsData.php’ file to process it.

  6. Damn. Sorry for mistakes and my whole knoledge of english. :)

  7. @sp

    I used your suggested method for a while but I found it wasn’t as portable as I’d like it. There is definate power to modularizing the logic into application functions and keeping the Server-Side Ajax handling separate. Handlers do that nicely. They handle the Ajax requests and call the exact same application functions that are used to generate the original page elements on first load.

    It is also important to note that I typically don’t use a single Ajax Handler in my applications. I split them up into appropriate categories. So if I were, say, doing an ecommerce site I may have an account handler, cart handler, and store handler. That is primarily for readability and findability of code ;)

    Now, if you are simply calling application functions within your xhr files, then we are on the same page, it seems. You simply like to split your function calls up a lot more than I do mine :)

  8. That’s a good start for an Ajax server in PHP. However, as I’ve found, it’s often necessary to have a more advanced response with various commands acting on incoming data, and it’s nice to be able to use PHP to push those commands to the client. My approach is to use something like xajax (which I’m a co-developer of, actually :) ) which lets you register functions or object methods, call them from Javascript with a simple function call, and then you can craft a response using a number of different commands via an easy-to-use response object in PHP.

    Check it out — it’s kind of neat, I think.

  9. BorkWeb Writing Your Server-Side Ajax Handler…

    In my recent post on ‘Ajax; Templating; and the Separation of Layout and Logic,’ I refer to an Ajax Handler that sits server side to handle Ajax calls. Some elaboration is in order.

    As I have stated in the past, I’m a huge fan of Prototype AND I …

  10. Chris Avatar
    Chris

    this maybe a more modular way to call to seperate classes

    $class =$_GET[‘class’];
    include_once($_SERVER[‘DOCUMENT_ROOT’].”/classLib/$class.class.php”);
    $obj = new $class();
    $methods = get_class_methods($obj);
    if (in_array($_GET[‘method’], $methods)) {
    $params = $_GET;
    unset($params[‘method’]);
    unset($params[‘class’]);
    $obj->$_GET[‘method’]($params);
    }else{
    die(‘Invalid call!’);
    }

  11. Cool project!

  12. Good site!
    Bye.

  13. […] MasterWish – a one and a half year old brainchild of a couple of other developers and myself – has been my playground after work hours. I began my experimentation with Ajax using that site, as PSU tended to slap my hand when looking into Ajax at work. Through that experimentation, I began to understand the workings of Ajax and how it would work into the PHP/Templating environment I was so comfortable with. Once I had dug down, I promptly posted my “Ajax; Templating; and the Separation of Layout and Logic” article that Ajaxian blogged about, along with the follow-up article. […]

  14. Thanks for your great site!

  15. I liked this site, it’s neat. Good job! Visit my sites, please:

  16. I was looking at your code.. its a great idea, however I was wondering why you dissected the $_GET variable in your dynamic handler when you could have simply passed the $_GET array to the ajax function (after unsetting the [‘function’] key). ie.

    $params = $_GET;
    //unset the function index from the params because we just don’t need it there

    unset($params[‘function’]);
    eval($_GET[‘function’].”($params);”);

    I was just curious because maybe im missing a good reason that I didn’t see. It just seems that you are doing twice the amount of work.

  17. Sorry, I just realized this is equal to your posted Variable Variable Method!

  18. I also wanted to let you know I am working on a version of this code to get $_POST variables to work as well since HTTP GET has a max header size and will not work for sending larger blobs of data! If anyone has any suggestions please post!