PHP DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Migrating Web-Based PHP Applications to Ajax
Pages: 1, 2

New Design

Here's the plan:



  1. Split the initial script into three files: static content (HTML), client-side processing (JavaScript), and server-side processing (PHP).
  2. Include jquery.js and the new JavaScript file in the HTML file.
  3. Add a unique id attributes to all dynamic content tags.
  4. Define JavaScript functions to make Ajax-style server calls and update page elements.

We can merge the dynamic and static content in one of two ways:

  • PHP returns the dynamic content as HTML, and JavaScript stuffs it into a page element with innerHTML.
  • PHP returns the dynamic content in a JSON-format data array, and JavaScript builds and inserts the HTML into the target page element.

Let's try both.

Version 2: Ajax Submit, HTML Return

In this method, PHP generates the HTML for the option tags, and we just stuff the HTML into the enclosing select. Now we start with an HTML file, and it's just a container:

people2.html:
<html>
<head><title>New Form Version 1</title>
<script src="jquery.js"></script>
<script src="people2.js"></script>
</head>
<body>
People<br>
<select id="people">
</select>
<br>
<table border=1>
<thead>
<tr><td>First Name</td><td>Last Name</td><td>Dance</td><td>Pie</td></tr>
</thead>
<tbody id="info">
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
</body>
</html>

Now let's look at the JavaScript file. jQuery's central function is $(), which returns a jQuery object. Its arguments may have many forms, but we'll use these now:

  • $(document): Selects the DOM document object.
  • $("#myid"): Selects the element with id="myid".

The jQuery call $(document).ready replaces window.onload. It's called when the DOM is ready, instead of waiting for all images to load. This avoids synchronization problems. All of the JavaScript functions that work with form elements can be in here.

The load() function calls the server script people.php and inserts its output into the select element with id people. This is the equivalent of the first chunk of the original version. It makes an Ajax connection to the server, and inserts the returned HTML into the element with id people:

(I've spread out the formatting to help distinguish the parentheses and curly brackets.)

people2.js:
$(document).ready
    (
    function()
        {
        // Call this when the DOM is ready:
        $("#people").load("people2.php?cmd=init");
        // Call this when a person is selected:
        $("#people").change(function()
            {
            // get the user's id from the selected option:
            var user_id = $(":selected").val();
            $("#info").load("people2.php?cmd=info&id=" + user_id);
            });
        }
    );

For this version, that's all the JavaScript we need. By the way, this approach has been called AHAH (Asynchronous HTML and HTTP). Now we'll look at the PHP script it calls. This version is like the original, but it only prints the HTML fragment for the current query:

people2.php:
  <?php
 
  $cmd    = @$_REQUEST["cmd"];
  $id    = @$_REQUEST["id"];
  mysql_connect($server, $user, $password);
mysql_select_db("test");
if ($cmd == "init")
        {
        $result = mysql_query("select id, fname, lname from people");
        echo "<option value=''>(select a person)\n";
        while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
                echo "<option value='$row[id]'>$row[fname] $row[lname]\n";
        }
elseif ($cmd == "info")
        {
        $id     = mysql_real_escape_string($id);
        $result = mysql_query("select * from people where id='$id'");
        $info = mysql_fetch_array($result, MYSQL_ASSOC);
        echo <<< END
<tr>
<td>$info[fname]</td>
<td>$info[lname]</td>
<td>$info[dance]</td>
<td>$info[pie]</td>
</tr>

END;
        }
?>

Although you could call this approach AJAJ, thankfully no one does.

Version 3: Ajax Submit, JSON Return

In this alternative, PHP builds a data array from the database query and returns it to JavaScript in JSON format. jQuery converts this JSON string into a jQuery object and passes it to a callback function, which builds the HTML for the options and inserts it into the appropriate page element. This example is the same as people2.html, except it calls people3.js:

people3.html:
<html>
<head><title>New Form Version 1</title>
<script src="jquery.js"></script>
<script src="people3.js"></script>
</head>
<body>
People<br>
<select id="people">
</select>
<br>
<table border=1>
<thead>
<tr><td>First Name</td><td>Last Name</td><td>Dance</td><td>Pie</td></tr>
</thead>
<tbody id="info">
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
</body>
</html>

We're just going to fill the container in a different way. In this version, we call getJSON with three arguments:

  • The URL
  • A dictionary of name:value pairs
  • A JavaScript callback function.

A GET URL will be built from the URL and name:value arguments, and the returned JSON string will be converted into a JavaScript object and passed to the callback function.

people3.js:
 $(document).ready
        (
        function()
                {
        // Call this when the DOM is ready:
                $.getJSON("people3.php",
                        { cmd : "init" },
                        make_menu);
        // Call this when a person is selected:
                $("#people").change(function()
                        {
                        var user_id = $(":selected").val();
                        $.getJSON("people3.php",
                                { cmd : "info", id: user_id  },
                                make_info);
                        });
                }
        );
function make_menu(obj)
        {
        var str = "";
        var len = obj.length;
        str += "<option value=''>(select a person)\n";
        for (var i = 0; i < len; i++)
                {
                var user = obj[i];
                str += "<option value='" + user["id"] + "'>" +
                        user["fname"] + " " +
                        user["lname"] + "\n";
                }
        $("#people").html(str);
        }
function make_info(info)
        {
        var str = "<tr>";
    // You can get each value as info.name or info["name"].
    // Let's get the first name using the first way.
        str += "<td>" + info.fname + "</td>";
        str += "<td>" + info["lname"] + "</td>";
        str += "<td>" + info["dance"] + "</td>";
        str += "<td>" + info["pie"] + "</td>";
        str += "</tr>\n";
        $("#info").html(str);
        }

This version of the PHP script is even simpler than people2.php. Instead of creating HTML from the database return values, we just encode the PHP data array in JSON format and send it off:

people3.php:
<?php
$cmd    = @$_REQUEST["cmd"];
$id     = @$_REQUEST["id"];
mysql_connect($server, $user, $password);
mysql_select_db("test");
if ($cmd == "init")
        {
        $result = mysql_query("select id, fname, lname from people");
        $user_array = array();
        while($row = mysql_fetch_array($result, MYSQL_ASSOC))
                $user_array[] = $row;
        echo json_encode($user_array);
        }
elseif ($cmd == "info")
        {
        $id = mysql_real_escape_string($id);
        $result = mysql_query("select * from people where id='$id'");
        $info = mysql_fetch_array($result, MYSQL_ASSOC);
        echo json_encode($info);
        }
?>

The json_encode function is included with standard PHP starting with version 5.2. For earlier versions, see the PHP JSON manual section.

If you chose our friend Alfredo from the menu, the JSON returned would look like this:

{"id":"1","fname":"Alfredo","lname":"de Darc","dance":"tango","pie":"blueberry"}

That JSON string is converted to a JavaScript object by jQuery and passed to the make_menu function as the info argument.

Judging the Makeover

The main choice between these new versions is where to do the output formatting: in PHP (version 2) or in JavaScript (version 3). Another factor might be what other plans you have for the data. Instead of throwing info away after generating the HTML in version 3, you could save it in a global JavaScript variable and use it for other purposes later.

Are these new versions better than the original? Let's see if our original promises were kept:

Separating dynamic content from static content.
All the static content is in the HTML file, and the dynamic data from the PHP script are processed in JavaScript for page placement.
 
Separating content, style, and processing.
We didn't show it here, but a separate CSS file would be a nice orthogonal addition.
 
Web client-server communication via function calls.
Good old Ajax.
 
Partial page updates instead of flash-bang page reloads.
Ajax again.
 
Faster development and more maintainable code.
PHP now just gets data from the database and returns output chunks (HTML or JSON) rather than whole pages.
 
Faster load times and improved caching.
people2.html, people2.js, people3.html, and people3.js are static files that will be cached by the browser (and the web server, which will make the application more scalable). The whole output page is also cached, the only changes being performed by JavaScript within the browser. Finally, we avoid a database lookup in every call to people2.php or people3.php after the first one.

The most important benefit is that the new approach will scale much better with future requirements, such as adding a new person or editing the data of an existing person. And new requirements are as sure as death and taxes.

Bill Lubanovic started developing software with UNIX in the 70s, GUIs in the 80s, and the Web in the 90s. He now does web visualization work for a wind energy company.


Return to the PHP DevCenter.


Valuable Online Certification Training

Online Certification for Your Career
Earn a Certificate for Professional Development from the University of Illinois Office of Continuing Education upon completion of each online certificate program.

PHP/SQL Programming Certificate — The PHP/SQL Programming Certificate series is comprised of four courses covering beginning to advanced PHP programming, beginning to advanced database programming using the SQL language, database theory, and integrated Web 2.0 programming using PHP and SQL on the Unix/Linux mySQL platform.

Enroll today!


Sponsored by: