Simple PHP Ajax tutorial

By Constantin Apetrei

In this post we want to explain how Ajax works in a simple web application with a PHP backend. The backend could be written in any other language (Python, Ruby, Java etc.) as long as the output format remains the same. Here, PHP is used simply to generate a data-oriented service response in JSON format, so it’s not like we are heading towards writing yet another bunch of spaghetti code anyway. But we digress…

 

We will implement an arithmetic application, which computes the result of an user-selectable operation on two operands (i.e. the 1+1=2 of Ajax).

The following picture shows a bird’s eye view of the process: when the user clicks on the “Compute link” a request will be made behind the scenes to the server, which will return a text response, which will be subsequently interpreted and used to display the result in the web page. As opposed to regular web applications, when on each click an entire new page is requested from the server and then displayed by the browser, here we stay on the same page and request from the server to perform a service, after which we update the interface accordingly. This technique is called Ajax.

The web interface of our application consists of two textboxes (for each operand), a dropdown menu (for selecting the operator), a Compute link, and a label where the result will be displayed.

To support us in better understanding what’s going on, we’ll use these two following Firefox extensions:

  • Live HTTP Headers – to view the data sent by the application to the server and vice-versa
  • Firebug – helps us in debugging javascript code

The application will be divided into two layers:

  • the business logic – basically the script that does the real work
  • the GUI – the form (“what you see”)

I. The business logic layer, is a piece of code written in PHP that takes the 3 parameters (the operands and the operator) sent to the server through a GET request, does the computing and displays the result on screen.

First of all, we will test this business logic layer by sending the parameters via the URL. For example, suppose our script is called arith.php; in the browser address window we can write (or copy paste) http://localhost/~costel/arith.php?operand1=1&operand2=1&operator=%2B. Mind that the first part of the web address will probably be different on your web server installation.

The file arith.php contains the following code:

<?header('Content-type: application/x-json');?>
<?
  $operand1 = $_GET['operand1'];
  $operand2 = $_GET['operand2'];
  $operator = $_GET['operator'];

  echo "{\n";
  echo "operand1: ",$operand1,",\n";
  echo "operand2: ",$operand2,",\n";
  echo "operator: \"",$operator,"\",\n";
  echo "result: ";

  switch($operator)
  {
    case '+':
      echo $operand1+$operand2;
      break;
    case '-':
      echo $operand1-$operand2;
      break;
    case '/':
      echo $operand1/$operand2;
      break;
    case '*':
      echo $operand1*$operand2;
      break;
  }

  echo "\n}";
?>

Let’s explain a bit what this does:

a. We specify the way our text will be interpreted by the browser; to direct the browser not to display the text like regular HTML, we’ll be using a application/x-json, a convention which implies that we send from the web server a text, formatted as JSON.

<?header('Content-type: application/x-json');?>

b. We take each parameter from the URL and store them into PHP variables.

$operand1 = $_GET['operand1'];
$operand2 = $_GET['operand2'];
$operator = $_GET['operator'];

c. We begin printing a response, formatted as JSON.

echo "{\n";
echo "operand1: ",$operand1,",\n";
echo "operand2: ",$operand2,",\n";
echo "operator: \"",$operator,"\",\n";
echo "result: ";

d. Depending on the type of the chosen operator we perform the appropriate computation, and print the result.

switch($operator)
{
  case '+':
    echo $operand1+$operand2;
    break;
  case '-':
    echo $operand1-$operand2;
    break;
  case '/':
    echo $operand1/$operand2;
    break;
  case '*':
    echo $operand1*$operand2;
    break;
}

Some care is required when the + operator is sent in the URL, because in the URL specification a + actually means a blank space. Because of that, we need to encode in the URL the + operator as %2B, so that on the receiving side PHP will decode it as a regular + string.

You might have noticed that our output isn’t a simple “Result: [result]” string, but somewhat different. We’ll come back on that a bit later.

II. The GUI is created by a file called do.php, which generates a simple HTML form with this code:

<form>
  Operand1 <input type="text" id="operand1" size="20"/>
  <select id="operator">
    <option selected="selected">+</option>
    <option>-</option>
    <option>*</option>
    <option>/</option>
  </select>
  Operand2 <input type="text" id="operand2" size="20"/><br/>
</form>
<a href="#" onclick="handleCompute()">Compute</a>
<span id="result">...</span>

As previously mentioned, this code creates the following:

  • two text boxes for the operands (as you can see from the 2 <input type="text"> tags)
  • a dropdown menu (this is done by the <select> tag and its options inside it)
  • a link that acts like a button: when clicked the page displayed by the browser does not change (see the href="#" attribute), instead a JavaScript function handleCompute() is invoked
  • a simple label where the result will be displayed, initially containing only “…”

Each HTML object has an id that will be later used to either read or write its contents.

If we would have had a regular submit button instead of the link, and the form’s action were set to arith.php, the browser would navigate upon submit to a page which would look like:
{
operand1: 1,
operand2: 1,
operator: "+",
result: 2
}

But we will not use this “aged” technique, which would navigate us away from the GUI page. Instead, we will simulate the form submit behind the scenes, retrieve the results and update our page accordingly. This is Ajax.

When we test the business logic, we can enter in another browser tab an URL like this one: http://localhost/~costel/arith.php?operand1=1&operand2=1&operator=%2B. You will get in response a response as the one above. It is interesting to use the Live HTTP Headers plugin to view in greater deal what is being sent. To use the plugin, simply select Tools from the Firefox menu, then Live HTTP Headers.

Let us now discuss how we can make this form submission behind the scenes when the link is clicked. Our handleCompute() function looks like this:

function handleCompute() {
  var url,op1,op2,op;
  op1=document.getElementById("operand1").value;
  op2=document.getElementById("operand2").value;
  op=document.getElementById("operator").value;
  console.log("Computing...");

  url="arith.php?"+"operand1="+op1+"&operand2="+op2+"&operator="+encodeURIComponent(op);
  console.log(url);

  var request = new XMLHttpRequest();
  request.open("GET",url,true);
  request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

  request.onreadystatechange = function() {
    var done = 4, ok = 200;
    console.log("ajax callback state=", request.readyState);

    if (request.readyState == done && request.status == ok) {
      console.log("Got response ok, contents: ", request.responseText);
      var obj = eval("("+request.responseText+")");
      document.getElementById("result").innerHTML = " " + obj.operand1 +" "+obj.operator+" "+obj.operand2+" = "+obj.result;
    }
    else
      document.getElementById("result").innerHTML = "<b>Server not available</b>";
  }

  request.send("");
}

Some explanations now:

a. We get that data from each field of the form and store it into a JavaScript variable.

var url,op1,op2,op;
op1=document.getElementById("operand1").value;
op2=document.getElementById("operand2").value;
op=document.getElementById("operator").value;

b. We build the URL string that is used by the PHP script to do the math. The encodeURIComponent() function formats special characters in hex so they are URL compliant (see the discussion about + above).

url="arith.php?"+"operand1="+op1+"&operand2="+op2+"&operator="+encodeURIComponent(op);

c. Now we invoke our computing script to the server using an XMLHttpRequest object (which is basically used to send data – text or xml – between a web server and a browser without leaving the current page).

var request = new XMLHttpRequest();
request.open("GET",url,true);
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

d. The onreadystatechange function is called whenever something worthwhile happens with our request to the server, but we will be interested only in differentiating success from failure. When success happens, 4 states must be passed through, the last response status should be 200 (OK), and the server reponse is stored in the request.responseText variable.

request.onreadystatechange = function() {
var done = 4, ok = 200;
console.log("ajax callback state=", request.readyState);

if (request.readyState == done && request.status == ok) {
  console.log("Got response ok, contents: ", request.responseText);
  var obj = eval("("+request.responseText+")");
  document.getElementById("result").innerHTML = " " + obj.operand1 +" "+obj.operator+" "+obj.operand2+" = "+obj.result;
}
else
  document.getElementById("result").innerHTML = "<b>Server not available</b>";
}

Here’s something interesting: as you remember, we formatted the output of the script in a “special” way:
{
operand1: 1,
operand2: 1,
operator: "+",
result: 2
}

This allows us to use JavaScript to create an object, using the eval() function, that has exactly these attributes (operand1operand2,operatorresult) and their values are set accordingly. The code displays the result by setting the innerHTML of the result div element on success, and simply accesses these properties using the straightforward object.attribute notation. Nice, huh?

The innerHTML property is used to set the contents <span> tag.

Note: We have used Firebug to debug our application by printing messages to the console in certain keypoints. Do not forget when you first activate the module from the Tools menu of Firefox to go in Firebug’s Console and enable the first two checkboxes, Console and Script, then click the “Apply settings” button.

Conclusions

In this post we wanted to explain how Ajax works at the “low level”. Of course, in a real application we probably will exercise more care in handling error cases and most likely we will use a library such as Prototype to make our life easier.

References

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>