The "Hello World" of Ajax and PHP

The "Hello World" of Ajax can be intimidating because there is more than one language involved: PHP and JavaScript. Unlike in a traditional web application where most of the presentation and data processing is handled by PHP (or any server-side language for that matter), in Ajax applications PHP only creates the data and it is up to the JavaScript on the client side to interpret that data.

If you are unfamiliar with PHP 5 you may want to take a moment to look at the Appendix for an overview of what relevant features have changed between versions 4 and 5.

After receiving a request to an Ajax-enabled PHP page, the server then returns the page as it normally would. The magic occurs when we include JavaScript in the served page that is linked to actions. Once one of those actions occurs, an asynchronous request will be made to the server. The server then returns the requested data, which JavaScript can act on accordingly (see Figure 1).

Generic sequence diagram for a typical Ajax application

Figure 1. Generic sequence diagram for a typical Ajax application

We can see that the actor (client viewing your web page) makes a request to view the selected page where he is served a mix of HTML, JavaScript, and most likely images. The JavaScript is designed so that by using Ajax the user can perform an action and receive data in return without leaving or reloading the page he is currently viewing.

Because the page is being served by PHP, we have the benefit of a powerful scripting language on our side. In this example, we serve a page to the web browser and then request and display the system date and time from the server without ever leaving or reloading the page.

The PHP File

The PHP is basic. If the client passes the variable "NOW" via the GET method, then the server will return the date and time, as well as a little message to, hopefully, bring back some memories. POST and GET are the two primary methods (in addition to HEAD and several others) of retrieving a page via HTTP. They each have the added ability of being able to pass variables to the server. In the case of GET, the variables are stored in the URL encoded as a query string (the part of the URL that appears after the first question mark).

We want to create a page that displays the time on the server when the user clicks a button. To do this we have a simple PHP script:

<?php
function get_message()
{
       return "Hello world! It is ".date("r");
}
if ( isset( $_GET["NOW"] ) ) {
       header("Cache-Control: no-cache, must-revalidate");
       header("Content-type: text/plain");
       echo get_message();
} else { ?>
<html>
<head>
       <title>Hello world</title>
       <!-- insert JavaScript here -->
</head>
<body>
       <div id="data">
              <?
              if ( isset($_GET["NOW-INLINE"]) )
                     echo get_message();
              else echo "Press Go";
              ?>
       </div>
       <a href="?NOW-INLINE" id="action">Go</a>
</body>
</html>
<?php } ?>

Let's analyze this file. If you know HTML, you should recognize the metadata inside the "else" block as HTML formatted information. The page isn't anything special. However, here our focus is on functionality, not on aesthetics.

The function get_message() returns the formatted date and time. We moved the echo to a separate function because it is used twice: when the $_GET["INLINE"] variable is set and when NOW-INLINE is set.

Put this page in a directory that is accessible via your web server. Then load it into a browser on your client computer. Assuming PHP is configured properly, you will see a page with the text "Press Go" and a link that says "Go" under to it. Now click on the link. You should be taken to a page that reads "Hello world! It is Mon, 12 Feb 2007 13:43:00 −0600. Go." If you see that page with your server's current date and time, then we are off to a good start. However, this page currently doesn't contain any JavaScript and certainly doesn't contain any asynchronous requests. Next, we add JavaScript to make this example a complete Ajax application.

The JavaScript

This example uses in-file JavaScript. Other examples in the text will store the JavaScript in external files. For now, the JavaScript code should be inserted where the <!-- insert JavaScript here --> comment is in the previous PHP script:

<script type="text/javascript">
<!--
var httpObj=null;
function OnLoad()
{
       document.getElementById("action").href="javascript:Update()";
}
function Update()
{
       if ( httpObj != null ) return;
       document.getElementById("data").innerHTML = "Loading";
       httpObj = NewHTTP();
       httpObj.open("GET","?NOW",true);
       httpObj.onreadystatechange = OnData;
       httpObj.send(null);
}
function NewHTTP()
{
       try {
              return new XMLHttpRequest();
       } catch (e) {
              return new ActiveXObject("Microsoft.XMLHTTP");
       }
}
function OnData()
{
       if ( httpObj.readyState==4 ) {
              m=document.getElementById("data");
              if (httpObj.status==200 ) {
                     m.innerHTML = httpObj.responseText;
              } else {
                     m.innerHTML="Error loading date and time.";
              }
              httpObj = null;
       }
}
-->
</script>

The first function called is OnLoad() and it should be executed when the page finishes loading. We will see more of it later in the "Unobtrusive JavaScript section."

The meat and bones of the script is the Update() function, which will be called when the go button is clicked. This event will perform several tasks.

  • Check to make sure the httpObj variable is null. If it isn't, then a request is already occurring so don't resend the same request.

  • Set the text inside our box to "Loading." Even though the script will function without it, this step is important and should not be left out because it provides immediate feedback to the user. Without it, the user may not know that the data is being transferred in the background and could become frustrated. A frustrated user may press the Refresh button or leave the web application altogether. Whenever possible, always provide this type of feedback to avoid confusing or frustrating the user. For example, in Web 2.0 applications this is typically done with a ball revolving in a circle to signify "Loading" until the content transfer is complete.

  • Create a new XMLHttpRequest object via the user defined NewHTTP() function.

  • Call the open() method, which tells the object the specific page to request from the server. Be aware that, at this point, no data has been sent to the server. The first parameter is the method used to retrieve the file. As hinted at earlier, this is commonly either GET or POST.

  • Specify the actual URL to load. This can be done using a relative or absolute URL. In a relative URL, we specify only the path to the file in relation to the file the user is currently viewing. If we were using an absolute URL, then we would include the full path to the file. In this case we, want to fetch the current page using the query string "NOW" so we use the relative URL "?NOW" in our request. This tells the browser to fetch the current page with the query string. Also in the open() method, we specify that this is an asynchronous request by using true. If the third parameter is false, the script halts execution until after the file is loaded and then continues. Since it is true, the script resumes execution immediately and leaves status handling to the callback function.

  • Assign the callback function. A callback function is a user-defined function that is stored and later called when it is needed, allowing us to define our own code that executes when an event happens. In this case, the function is called when an HTTP event occurs that affects the ready state of the request. In our example, it is OnData(). The ready state can be thought of as the status of the request.

  • Make the actual request for the page from the server, now that we have all the information necessary. The send method makes the request. If the object is asynchronous (which it is in this example), then this method returns immediately. Otherwise, it waits for the page to load or a failure to occur.

The XMLHTTPRequestObject

Microsoft invented the XMLHTTPRequest object in the form of an ActiveX control called XMLHTTP. It is an object that makes it possible for the client to request files using the HTTP protocol. If the file is XML, then it will be automatically interpreted as such.

The other browser manufacturers saw this and implemented the same functionality. Unfortunately, Internet Explorer is the only major browser that natively uses ActiveX controls. (Therefore, the XMLHTTPRequest object was born.) The Internet Explorer version behaves the same but it is initialized differently than the way most other browsers initialize it. This, unfortunately, muddies the waters when creating new request objects. For this reason, we move the creation of new objects to a separate function so we can more easily create multiple requests without duplicating the four lines of code it takes to create the object. Most browsers—including Microsoft's Internet Explorer 7—recognize and use the XMLHttpRequest object, however, if that fails (e.g., on Internet Explorer 6), we fall back to the XMLHTTP ActiveX object, which works only in Internet Explorer. Use the try/catch block to do this as you saw previously in the NewHTTP function.

Create the XMLHttpRequest before creating the ActiveX control because, as of Internet Explorer 7, you can use either; initialize the one that is most likely to be successful.

Note

It can sometimes be confusing to work with multiple languages in the same project because PHP 4 does not have exception handling (try/catch). However, this is not a limitation in JavaScript. You can use try/catch in your JavaScript regardless of the version of PHP you use.

Ready State and Status

We already set a callback function to be executed whenever the ready state of the request changes. This callback function is seen in the form of "OnData" in the example.

You may have noticed that we have a global variable httpObj that stores the instance of the XMLHTTPRequest. We reference this object again in the OnData function.

The "readyState" property can be 0 to 4 where 0 is initialized and the number 4 is analogous to complete. In this example, we only worry about state 4. However, we still need to check to make sure it is actually complete (4) because the function can and will be called with some of the other values as well. Once the document has loaded completely, we get a pointer to the div (box) we created earlier. Next, we check to see if the page load was successful by checking the status code. Status code is a standard HTTP response code. You probably recognize 404 as the "File not found" error. We want to get a 200 response, which lets us know the operation was successful.

Finally, free the XMLHTTPRequest object by setting the only variables referencing it to null. This frees up some of the memory and helps prevent leaks and slowdown that can occur in some browsers by leaving the object initialized for too long.

Unobtrusive JavaScript

If you insert the JavaScript code into your file, you may notice that clicking the "Go" link still reloads the page just as before instead of asynchronously fetching the information. The reason for this is that we haven't changed the href of the link, so none of our nice new JavaScript is called. If you already changed the link, then take a step back for a minute. Congratulations, you now have a working Ajax program. However, there is one small issue.

Changing the link in the HMTL makes it useless for people with JavaScript disabled. This may seem trivial but some people choose not to use JavaScript and some browsers don't allow JavaScript. Failing to accommodate these people can lose you potential customers. Instead use unobtrusive JavaScript.

Unobtrusive JavaScript is a term coined to describe JavaScript that does not interfere with the style or layout elements of the page. It is also fault tolerant and degrades gracefully on less-than-capable browsers (e.g., browsers with JavaScript disabled).

That is where the "onLoad" event comes into play. Change the body tag on your page to look like this:

<body onLoad="OnLoad();">

This tells your browser to call the OnLoad() function when all the elements of a page finish loading. In this case, all the function does is change the href of the link on the client-side to equal the appropriate JavaScript call.

Obviously, you cannot use unobtrusive JavaScript in all cases—such as when working with an existing system—but, whenever you can, you should consider it. Ultimately, it is up to the webmaster to decide if she wants a site that's accessible to both people with and without JavaScript capabilities.

Quick Testing Tips

Sometimes if you have a fast server and a low latency connection to it, the page will load exceptionally fast so that you barely (if at all) notice when the transition elements appear. In the previous example, we displayed a "Loading" message, which goes away once the asynchronous request finishes. However, when we test the script on some servers, the loading image will appear then quickly disappear in the blink of an eye. When this happens, new Ajax users may have a tough time believing that any asynchronous action is occurring at all.

To demonstrate the concepts a bit more completely we can quickly add one line of PHP to our script.

First, we find the line of code that checks for the GET variable NOW. Then we alter it so that it appears like code below:

if ( isset( $_GET["NOW"] ) ) {
       sleep(5);

Now when the asynchronous request is made, the server will pause for five seconds and then send the content. This simulates an exceptionally long server lag, which may happen if the web site is being hit by thousands of visitors. The 5 can be changed to any positive number.

One side effect of this lag is that the user may think the page is frozen or not responding. To help with this, use an animated GIF instead of the text "Loading" to display the status to the user.

Review

If all went well, you should now have a working Ajax and PHP application. Obviously, this particular application could be improved. For one, the script is not entirely unobtrusive. We could, for instance, move the JavaScript and CSS to an external file to further separate the script and the data/layout. However, you should now have a complete enough understanding of the concepts to be able to follow the rest of this Short Cut.

In this section, we covered:

  • The basics of the XMLHTTPRequest object.

  • What ready states are and how to use the ready states and callback functions to handle a request response once it is received.

  • How to serve up different content depending on how the page was requested.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
98.82.120.188