Building AJAX Applications with PHP and HTML_AJAX

January 25, 2009

Uncategorized

The Need For Speed

Unless you’ve spent the past couple of years down a rabbit hole, you’ve already heard about AJAX: it’s a technique that combines asynchronous client-server communication with a set of existing toolkits (JavaScript, CSS, the DOM) to selectively update parts of a Web page, instead of the traditional “full page reload”. This produces applications that are quicker and more responsive to user input, resulting in a better user experience.

But what does all this have to do with PHP, you ask? Well, PHP is commonly used on the server end of the connection, to handle AJAX requests and send back responses. But that isn’t all it can do – with a little PEAR package called HTML_AJAX, you can use PHP to significantly simplify the work that goes into building and deploying an AJAX application.

That’s where this article comes in. Over the next few pages, I’m going to give you a quick run-down on the PEAR HTML_AJAX class, together with a few examples of how you can use it to AJAX-ify various Web applications. Keep reading, and be prepared to be amazed!

Getting Started

HTML_AJAX works by providing a well-defined API for creating, processing and handling AJAX requests and responses. This API (which has both JavaScript and PHP components) insulates you from the nitty-gritty of working with a browser’s XMLHttpRequest object, thereby offering significant time-saving benefits over the “roll your own” approach.

Before we get started, it’s important to state the assumptions this tutorial makes:

  • First, it assumes that you understand HTML, know the basics of JavaScript and DOM programming, and are familiar with basic AJAX concepts.
  • Second, it assumes that you have an Apache/PHP/MySQL development environment already set up, know the basics of PHP scripting, and are familiar with retrieving and processing SQL result sets in PHP.
  • Third, it assumes that you’ve managed to successfully install the HTML_AJAX package. For your reference, this package is freely available from pear.php.net/package/HTML_AJAX, and is currently maintained by Elizabeth Smith, Arpad Ray, Joshua Eichorn and others. To install the package using the PEAR installer, use the following command:
shell> pear install HTML_AJAX-beta


This article uses v0.5.6 (beta) of HTML_AJAX.

I should mention at this point that this tutorial is intended mainly for users new to HTML_AJAX. As such, it includes a general introduction to the package and how it works, but shies away from very complex examples. Once you’ve worked your way through this tutorial, you’ll find many more sophisticated applications for HTML_AJAX in the package documentation and on the HTML_AJAX home Web site.

The Bookworm Turns

Let’s begin with a simple example that demonstrates how HTML_AJAX works. Assume for a moment that you have a MySQL database containing the following book and author records:

Table: author
+----------+-----------------+
| AuthorID | AuthorName      |
+----------+-----------------+
|        1 | Stephen King    |
|        7 | John le Carre   |
|       21 | Agatha Christie |
+----------+-----------------+
Table: title
+---------+-----------------------------------+
| TitleID | TitleName                         |
+---------+-----------------------------------+
|     400 | Taken At The Flood                |
|     412 | The ABC Murders                   |
|      61 | Cards on the Table                |
|     681 | The Naive And Sentimental Lover   |
|     719 | The Secret Pilgrim                |
|     271 | Misery                            |
|     191 | Firestarter                       |
|     867 | A Most Wanted Man                 |
+---------+-----------------------------------+
Table: author_title
+---------+----------+
| TitleID | AuthorID |
+---------+----------+
|     400 |       21 |
|     412 |       21 |
|      61 |       21 |
|     681 |        7 |
|     719 |        7 |
|     271 |        1 |
|     191 |        1 |
|     867 |        7 |
+---------+----------+


Here’s a PHP script that accepts an author ID as input (as a GET parameter) and executes an SQL query to return a list of all the books written by that author, by joining the author_title and title tables:

<?php
// file: get_titles.php
// use author ID to retrieve linked books
// output is an unordered HTML list
if (isset($_GET['id'])) {
  try {
    $dbh = new PDO('mysql:host=localhost;dbname=library', 'user', 'pass');
    $id = $dbh->quote(trim($_GET['id']));
    $sql = "SELECT TitleName FROM title AS t, author_title AS at WHERE at.TitleID = t.TitleID AND at.AuthorID = $id";
    echo '<ul>';
    foreach($dbh->query($sql) as $row) {
      echo '<li>' . $row[0] . '</li>';
    }
    echo '</ul>';
    unset($dbh);
  } catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    exit;
  }
}
?>


This is all pretty simple so far. Now, how about adding some AJAX to the mix? Let’s say we want a Web page that lets the user click an author’s name, and have the page updated with the books written by that author. With HTML_AJAX, this is simplicity itself. The first step is to create an instance of the HTML_AJAX server, which is responsible for delivering the JavaScript components to the client. Here’s the code:

<?php
// file: ajax-server.php
// include class
include 'HTML/AJAX/Server.php';

// create server to handle requests
$server = new HTML_AJAX_Server();
$server->handleRequest();
?>


Next, build an HTML page that requests the necessary JavaScript components from the server, and then uses those components to make an AJAX call. Here’s the code:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script>
    function getBooks(id) {
      document.getElementById('books').innerHTML = HTML_AJAX.grab('get_titles.php?id='+id);
    }  
   </script>
  </head>
  <body>
    <h2>Authors</h2>
    <div id="authors">
      <ul>
        <li><a href="javascript:getBooks(1);">Stephen King</a></li>
        <li><a href="javascript:getBooks(21);">Agatha Christie</a></li>
        <li><a href="javascript:getBooks(7);">John le Carre</a></li>
      </ul>  
    </div>
    <h2>Books</h2>
    <div id="books">
    </div>      
  </body>
</html>


The first <script> element in this page sends a request to the server, which responds with the JavaScript client files needed for HTML_AJAX to work. This code produces a client-side HTML_AJAX object, which makes a bunch of important methods available to the client. The simplest of these is the grab() method, which performs a GET request to a specified URL and returns the result. In the script above, this method is invoked when the user clicks an author name; it then transmits a GET request to the PHP script with the author identifier and writes the output (as an unordered HTML list) to a <div> on the page.

Here’s what the output looks like:

Going POST-al

If you prefer POST to GET, replace the call to grab() with a call to post(), which accepts both a target URL and a payload object containing the data to be POST-ed. Here’s the revised code:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script>
    function getBooks(id) {
      document.getElementById('books').innerHTML = HTML_AJAX.post('get_titles.php?id='+id);
    }  
   </script>
  </head>

  <body>
    <h2>Authors</h2>
    <div id="authors">
      <ul>
        <li><a href="javascript:getBooks(1);">Stephen King</a></li>
        <li><a href="javascript:getBooks(21);">Agatha Christie</a></li>
        <li><a href="javascript:getBooks(7);">John le Carre</a></li>
      </ul>  
    </div>
    <h2>Books</h2>
    <div id="books">
    </div>      
  </body>
</html>


Remember that you’ll need to update the server-side script to use POST variables instead:

<?php
// file: get_titles.php
// use author ID to retrieve linked books
// output is an unordered HTML list
if (isset($_POST['id'])) {
  try {
    $dbh = new PDO('mysql:host=localhost;dbname=library', 'user', 'pass');
    $id = $dbh->quote(trim($_POST['id']));
    $sql = "SELECT TitleName FROM title AS t, author_title AS at WHERE at.TitleID = t.TitleID AND at.AuthorID = $id";
    echo '<ul>';
    foreach($dbh->query($sql) as $row) {
      echo '<li>' . $row[0] . '</li>';
    }
    echo '</ul>';
    unset($dbh);
  } catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    exit;
  }
}
?>


For asynchronous calls, both post() and grab() allow you to specify a callback method as optional third argument. Consider the following revision of the previous example, which demonstrates this technique:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script>
      function getBooks(author) {
        var payload = {id:author};
        HTML_AJAX.post('get_titles.php', payload, handleAJAXResponse);
      } 
      
      function handleAJAXResponse(resp) {
        document.getElementById('books').innerHTML = resp;      
      } 
   </script>
  </head>
  <body>
    <h2>Authors</h2>
    <div id="authors">
      <ul>
        <li><a href="javascript:getBooks(1);">Stephen King</a></li>
        <li><a href="javascript:getBooks(21);">Agatha Christie</a></li>
        <li><a href="javascript:getBooks(7);">John le Carre</a></li>
      </ul>  
    </div>
    <h2>Books</h2>
    <div id="books">
    </div>      
  </body>
</html>


Form and Function

An alternative approach, especially when working with forms, is to instead use HTML_AJAX’s formSubmit() method. This method needs only two arguments: the source form object, and the destination for the result. It then automatically detects the form’s action URL and method, transmits the form data, and writes the return value to the destination. Note that the destination argument to the method can be either a callback function, or an element on the page.

Here’s an example, which generates a form to calculate simple interest:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
  </head>
  <body>
    <h2>Simple Interest</h2>
    <form method="post" action="simple_interest.php" onSubmit="HTML_AJAX.formSubmit(this, 'result'); return false; ">
      <label>Principal:</label>
      <div>
        <input type="text" name="p" />
      </div>
      <label>Interest rate (%):</label>
      <div>
        <input type="text" name="r" />
      </div>
      <label>Number of years:</label>
      <div>
        <input type="text" name="n" />
      </div>
      <label>Result:</label>
      <div id="result">
      </div>
      <input type="submit" value="Calculate" />
    </form>
  </body>
</html>


Here’s what the form looks like:

Here’s the server-side script, which receives and processes the form input:

<?php
// file: simple_interest.php
if (is_numeric($_POST['p']) && is_numeric($_POST['r']) && is_numeric($_POST['n'])) {
  $p = $_POST['p'];
  $r = $_POST['r'];
  $n = $_POST['n'];
  $result = $p * $r/100 * $n;
  echo $result;
} else {
  echo 'Input error';  
}
?>


Once the user enters values into the form and submits it, the formSubmit() method submits the form data to the above script and writes the result to the aptly-named ‘result’ element. Here’s an example of the output after a sample run:

If you’d prefer, you can pass formSubmit() a callback method, as in the following revision (which produces equivalent output):

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script> 
    function handleAJAXResponse(ret) {
      document.getElementById('result').innerHTML = ret;
    }
    </script> 
  </head>
  <body>
    <h2>Simple Interest</h2>
    <form method="post" action="simple_interest.php" onSubmit="HTML_AJAX.formSubmit(this, handleAJAXResponse); return false;">
      <label>Principal:</label>
      <div>
        <input type="text" name="p" />
      </div>
      <label>Interest rate (%):</label>
      <div>
        <input type="text" name="r" />
      </div>
      <label>Number of years:</label>
      <div>
        <input type="text" name="n" />
      </div>
      <label>Result:</label>
      <div id="result">
      </div>
      <input type="submit" value="Calculate" />
    </form>
</body>
</html>


Time Travel

Another interesting method in HTML_AJAX is the replace() method, which allows you to replace the content of a destination element. To illustrate this, consider the following HTML page, which dynamically generates a monthly calendar using AJAX:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script>
    function displayCalendar() {
      // get selected month
      var mmList = document.getElementById('mm');
      var mm = mmList[mmList.selectedIndex].value;

      // get selected year
      var yyList = document.getElementById('yy');
      var yy = yyList[yyList.selectedIndex].value;
            
      // handle AJAX request/response
      // replace in specified container
      url = 'get_calendar.php?mm=' + mm + '&yy=' + yy;
      HTML_AJAX.replace('calendar', url); 
    }
    </script>
  </head>
  <body>
    <form>
      <select name="mm" id="mm">
        <option value="01">Jan</option>
        <option value="02">Feb</option>
        <option value="03">Mar</option>
        <option value="04">Apr</option>
        <option value="05">May</option>
        <option value="06">Jun</option>
        <option value="07">Jul</option>
        <option value="08">Aug</option>
        <option value="09">Sep</option>
        <option value="10">Oct</option>
        <option value="11">Nov</option>
        <option value="12">Dec</option>
      </select>
      <select name="yy" id="yy">
        <option value="2009">2009</option>
        <option value="2010">2010</option>
        <option value="2011">2011</option>
        <option value="2012">2012</option>
        <option value="2013">2013</option>
        <option value="2014">2014</option>
        <option value="2015">2015</option>
      </select>
      <input type="submit" value="Display" onClick="javascript:displayCalendar(); return false;" />
    </form>
    <div id="calendar">
    </div>
  </body>
</html>


Here’s what this form looks like:

Once the form is submitted, the displayCalendar() method retrieves the selected values and formulates them into a GET request for a server-side script. The output generated by the script is a calendar for the specified month and year, and the replace() method is used to place this output in the ‘calendar’ element on the page. If the user re-submits the form with a new month and year, a new calendar will be generated and written to the element, overwriting the previous one.

Here’s the server-side script which generates the calendar:

<?php
// file: get_calendar.php
// include Calendar class
include "Calendar/Month/Weekdays.php";
include "Calendar/Day.php";

// get variables
$yy = isset($_GET['yy']) ? $_GET['yy'] : date('Y');
$mm = isset($_GET['mm']) ? $_GET['mm'] : date('m');

// initialize calendar object
$month = new Calendar_Month_Weekdays($yy, $mm);

// build child objects (days of the month)
$month->build();

// format as table
echo "<pre>";

// print month and year on first line
echo "          " . sprintf("%02d", $month->thisMonth()) . "/" . $month->thisYear() . "\n";

// print day names on second line
echo "  M   T   W   T   F   S   S\n";

// iterate over day collection
while ($day = $month->fetch()) {
  if ($day->isEmpty()) {
    echo "    ";
  } else {
    echo sprintf("%3d", $day->thisDay()) . " ";
  }
  
  if ($day->isLast()) {
    echo "\n";
  }
}
echo "</pre>";
?>


This script makes use of the PEAR Calendar class (read more about it at http://www.melonfire.com/community/columns/trog/article.php?id=277) to produce a monthly calendar, using the data provided in the GET request string. Here’s an example of what the output looks like:

An alternative to the replace() method is the append() method which – as you might guess – adds new content to the specified element instead of overwriting it. If you were to alter the code in the previous example to call append() instead of replace(), you’d end up with something like this:

The replace() method can come in handy when you need to rewrite specific sections of a page with new content – for example, when paging through a data set. For a good example of this technique in combination with PEAR’s Pager class, take a look at Lorenzo Alberton’s tutorial on the topic.

An Object Lesson

HTML_AJAX also supports calling PHP object methods from JavaScript – an interesting feature, and one that comes in particular handy when your server-side application is object-based. To do this, it’s necessary to first create an instance of the object and register it with the HTML_AJAX server, as below:

<?php
// file: ajax-server.php
// define class
class MyObj {
  function checkNum($num) {    
    if ($num <= 0) {
      return 'Number is 0 or smaller';      
    } else if ($num >= 20) {
      return 'Number is 20 or larger';
    } else if (!($num & 1)) {
      return 'Number is even';
    } else {
      return 'Good number';
    }
  }
}

// include class file
include 'HTML/AJAX/Server.php';

// instantiate server
$server = new HTML_AJAX_Server();

// register class with server
$obj = new MyObj();
$server->registerClass($obj);
$server->handleRequest();
?>
Then, within your Web page, call a method like replace() and - instead of a URL - pass it the class name, method name and method arguments, as below:
<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script>
    function testNum() {
      HTML_AJAX.defaultServerUrl = 'ajax-server.php';
      var val = document.getElementById('num').value;
      ret = HTML_AJAX.replace('result', 'MyObj', 'checkNum', val);
    }
    </script>
  </head>
  <body>
    <form>
      Enter an odd number greater than 0 and less than 20:
      <br/>
      <input name="num" id="num" />
      <input type="submit" value="Display" onClick="javascript:testNum(); return false;" />
    </form>
    <div id="result">
    </div>
  </body>
</html>


Here’s what the output looks like:

You can also use HTML_AJAX’s call() method for this purpose. This method accepts, as arguments, the class name, method name, local callback function name, and one or more method arguments. It then invokes the corresponding class method on the server and returns the output to the callback function.
To see an example of this in action, modify the class definition on the server to return true or false, instead of a string value:

<?php
class MyObj {
  function checkNum($num) {    
    if ($num <= 0 || $num >= 20 || !($num & 1)) {
      return false;      
    } else {
      return true;
    }
  }
}
?>


Then, update the Web page to use call() instead of replace(), and define a callback function that reads the result of call() and adjusts the output accordingly:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
  </head>
    <script>
    function testNum() {
      HTML_AJAX.defaultServerUrl = 'ajax-server.php';
      var val = document.getElementById('num').value;
      HTML_AJAX.call('MyObj','checkNum', myCallback, val);
    }
    
    function myCallback(ret) {

      if (ret == 1) {
        document.getElementById('result').innerHTML = 'Good number';
      } else {
        document.getElementById('result').innerHTML = 'Bad number';       
      }
    }
    </script>
  </head>
  <body>
    <form>
      Enter an odd number greater than 0 and less than 20:
      <br/>
      <input name="num" id="num" />
      <input type="submit" value="Display" onClick="javascript:testNum(); return false;" />
    </form>
    <div id="result">
    </div>
  </body>
</html>


A Proxy War

HTML_AJAX has the capability to automatically generate “proxy objects” in JavaScript, that serve as stubs to your PHP objects. You can then call proxy object methods inside your JavaScript code, and these will be translated into calls to the corresponding “real” methods in your PHP objects.
To illustrate how this works, let’s consider a simple AJAX-based login form. Assume that you have a MySQL table containing the following usernames and passwords:

Table: users
+----+----------+-------------------+-------------+
| id | username | password          | realname    |
+----+----------+-------------------+-------------+
|  1 | santa    | *F5C1C03AB4402... | Santa Claus |
|  2 | jane     | *0FD9A3F0F816D... | Jane Doe    |
+----+----------+-------------------+-------------+


Assume also that you have a simple Auth class that interacts with this table and checks user credentials. Here’s what the code might look like:

<?php
class Auth {
  function login($username, $password) {  
    // check for required values
    if (empty($username) || empty($password)) {
      throw new Exception('Missing username or password.');
      return false; 
    }
    
    // query
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    $sql = "SELECT realname FROM users AS u WHERE u.username = '$username' and u.password = PASSWORD('$password')";
    $row = $dbh->query($sql);
    $name = $row->fetchColumn();

    // return result
    if (!empty($name)) {
      return $name;
    } else {
      throw new Exception('Invalid username or password.');
      return false; 
    }
    
    unset($dbh);
  }
}
?>


This class should be registered with the HTML_AJAX server, as explained previously:

<?php
// file: ajax-server.php
// include class files
include 'HTML/AJAX/Server.php';
include 'Auth.php';

// instantiate server
$server = new HTML_AJAX_Server();

// register class with server
$obj = new Auth();
$server->registerClass($obj);
$server->handleRequest();
?>


On the client side, we need a login form that asks the user for his/her username and password, and then calls Auth->login() to verify these. One way to do this is with HTML_AJAX’s call() method. Another is to use a JavaScript proxy object:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script type="text/javascript" src="ajax-server.php?stub=Auth"></script>
    <script>
    // get input and call proxy object
    function doLogin() {
      var u = document.getElementById('u').value;
      var p = document.getElementById('p').value;
      auth.login(u, p);
    }
    
    // handle response from login 
    var myCallback = {
      login: function(ret) {
        if (ret) {
          document.getElementById('msg').style.border = 'solid 2px green'; 
          document.getElementById('msg').innerHTML = 'Welcome back, <strong>' + ret + '</strong>!'; 
        } else {
          document.getElementById('msg').style.border = 'solid 2px red'; 
          document.getElementById('msg').innerHTML = 'Invalid login!';          
        }
      }
    }  
      
    // create proxy
    var auth = new Auth(myCallback);
    </script>  
  </head>
  <body>
    <form>
      <label>Username:</label>
      <div>
        <input type="text" id="u" />
      </div>
      <label>Password:</label>
      <div>
        <input type="password" id="p" />
      </div>
      <input type="submit" value="Login" onClick="javascript:doLogin(); return false;"/>      
    </form>
    <div id="msg" style="width:200px; height:20px; margin:auto; text-align:center">
    </div>

  </body>
</html>


This isn’t as complicated as it looks, I promise! As usual, the first step is to load all the necessary JavaScript code. But there’s a twist here: look at the second <script> element, which uses the ?stub=Auth argument to auto-generate a “local” JavaScript object with the same methods as the remote PHP object. This local object, or proxy, serves as an entry point to all the methods of the remote object.

Here’s what the auto-generated proxy looks like:

// Client stub for the Auth PHP Class
function Auth(callback) {
	mode = 'sync';
	if (callback) { mode = 'async'; }
	this.className = 'Auth';
	this.dispatcher = new HTML_AJAX_Dispatcher(this.className,mode,callback,'/ajax-server.php?','JSON');
}
Auth.prototype  = {
	Sync: function() { this.dispatcher.Sync(); }, 
	Async: function(callback) { this.dispatcher.Async(callback); },
	login: function() { return this.dispatcher.doCall('login',arguments); }
}


With this, client scripts can reference the login() method of the local Auth proxy, rather than using call() to invoke the login() method of the remote PHP class. The value returned by login() is passed to the method’s callback function, which responds by using the DOM to display an appropriately color-coded message (red for failure, green for success) to the user.

Here are some screenshots illustrating the output (try logging in as ‘santa’ with password ‘northpole’):


Lights! Camera! Action

The HTML_AJAX package also provides “actions”, which help you manipulate elements on your Web page by writing the necessary JavaScript code for you. Actions expose methods, such as assignAttr(), insertScript() and insertAlert() which, respectively, deliver client-side code to dynamically access and manipulate element properties, insert script blocks or set up JavaScript alerts.

To illustrate, consider the following revision of the PHP Auth class, which uses Actions to accomplish the same result as the JavaScript code in the earlier example:

<?php
class Auth {
  function login($username, $password) {    
    // include class    
    include 'HTML/AJAX/Action.php';
    $action = new HTML_AJAX_Action();
    
    try {
      // check for required values
      if (empty($username) || empty($password)) {
        throw new Exception('Missing username or password.');
      }
      
      // query
      $dbh = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
      $sql = "SELECT realname FROM users AS u WHERE u.username = '$username' and u.password = PASSWORD('$password')";
      $row = $dbh->query($sql);
      $name = $row->fetchColumn();
      
      // return result
      if (!empty($name)) {
        $action->assignAttr('msg', array(
          'style'     => 'border: solid 2px green',
          'innerHTML' => 'Welcome back, <strong>' . $name . '</strong>'
        ));
      } else {
        throw new Exception('Invalid username or password.');
      }    
      unset($dbh);    
      
    } catch (Exception $e) {
      $action->assignAttr('msg', array(
        'style'     => 'border: solid 2px red',
        'innerHTML' => $e->getMessage()
      ));      
    }
    return $action;
  }
}
?>


Within the Web page, now, the callback function has no work to do:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script type="text/javascript" src="ajax-server.php?stub=Auth"></script>
    <script>
    function doLogin() {
      var u = document.getElementById('u').value;
      var p = document.getElementById('p').value;
      auth.login(u, p);
    }
    
    var myCallback = {
      login: function(ret) {
        return false;
      }
    }    

    var auth = new Auth(myCallback);
    </script>  
  </head>
  <body>
   ...
  </body>
</html>


HTML_AJAX also includes another class of helpers, called “behaviors”. Behaviors work like CSS, in that they allow you to attach JavaScript code to particular elements using CSS-type selectors. These helpers come in handy to ensure that, in the author’s words, “you don’t pollute your HTML with a ton of inline JavaScript.”


To illustrate how Behaviors work, consider a further revision of the login form – in this case, with the actual call to doLogin() nestled inside a Behavior instead of the submit button’s ‘onClick’ handler:

<html>
  <head>
    <script type="text/javascript" src="ajax-server.php?client=all"></script>
    <script type="text/javascript" src="ajax-server.php?stub=Auth"></script>
    <script>
    function doLogin() {
      var u = document.getElementById('u').value;
      var p = document.getElementById('p').value;
      auth.login(u, p);
    }
    
    var myCallback = {
      login: function(ret) {
        return false;
      }
    }
        
    Behavior.register(
      ".login_btn",  function(element) {
        element.onclick = function(){
          doLogin();  
        }
      }
    );    
    
    // create a proxy in async mode
    var auth = new Auth(myCallback);
    </script>  
  </head>
  <body>
    <form>
      <label>Username:</label>
      <div>
        <input type="text" id="u" />
      </div>
      <label>Password:</label>
      <div>
        <input type="password" id="p" />
      </div>
      <input type="button" value="Login" class="login_btn"/>      
    </form>
    <div id="msg" style="width:200px; height:20px; margin:auto; text-align:center">
    </div>
  </body> 
</html>


In this case, a Behavior is registered for the ‘login_btn’ class, such that the doLogin() function is invoked when elements of that class receive a mouse click. The end result remains the same as before, but this approach can help produce more structured code, as well as allow you to apply a particular behavior to multiple elements without unnecessary duplication of code.

As these examples illustrate, using HTML_AJAX can significantly reduce the drudge work involved in AJAX-ifying your application. As such, it’s a valuable addition to any programmer’s toolkit, and one that you should definitely take some time out to experiment with. Play with it sometime, and see what you think!

Copyright Melonfire, 2009. All rights reserved.

2 Responses to “Building AJAX Applications with PHP and HTML_AJAX”

  1. Moargan Says:

    Great article, I’ve been wanting to get into using AJAX with my scripts, but I’ve always been a little gunshy of it. I think this is the little extra I needed to jump in.

    @ j_tree1
    I think this article was written on the assumption that you can add your own security to your scripts. It’s much easier to just write functions for what you’re actually teaching than adding everything needed for a production model. It makes things a lot less confusing to do it that way.

  2. j_tree1 Says:

    The article has some great information and excellent examples but the sample code is filled with security vulnerabilities.

    example:

    What would happen if I navigated to:

    http://HOST/get_titles.php?id=‘;+drop+table+titles;–

    Little Bobby Tables </xkcd>