Advance PHP 6 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Explain AJAX and how its asynchronous model differs from the classic web application model.
  • Create and use the XMLHttpRequest object: open(), send(), setRequestHeader(), onreadystatechange, readyState, status, responseText, responseXML.
  • Distinguish synchronous and asynchronous requests and compare XMLHttpRequest with IFrames.
  • Build PHP + MySQLi back ends for AJAX: live search, form posting and XML responses.
  • Exchange data as JSON with json_encode(), json_decode() and the modern fetch() API.
What is AJAX?

AJAX – Asynchronous JavaScript And XML – is not a new language but a technique. It describes how existing technologies – JavaScript, the DOM (Document Object Model), XML (or JSON) and the XMLHttpRequest object – are used together to create interactive web applications.

When web applications were first built with these technologies separately, users could not work with them as smoothly as with desktop applications: every click sent the whole page to the server and waited for a complete new page. In 2005 Jesse James Garrett of Adaptive Path gave the combination of JavaScript, XML and the DOM the name AJAX. In this technique the request to the web server is sent with the XMLHttpRequest object, a part of JavaScript, which sends asynchronous requests. The page does not have to be reloaded; only the part that changes is updated, so the application behaves much more like a desktop application. Google Maps, Gmail, search suggestions and "like" buttons all work this way.

The AJAX Web Application Model

The AJAX application removes the start–stop–start–stop nature – the click, wait and refresh – of the classic client/server interaction. An AJAX engine, written in JavaScript, is introduced as an intermediary layer between the user and the web server:

Browser – user interface The user types or clicks; a JavaScript function is called instead of loading a new page.
↓
AJAX engine (JavaScript) Creates an XMLHttpRequest, sends an HTTP request in the background and keeps the page usable.
↓
Web server (Apache + PHP) Runs the server-side logic and the database query, and returns data – XML, JSON, HTML or text – not a whole page.
↓
AJAX engine Receives the response, and JavaScript updates only the part of the page that changed (via the DOM).

Figure 39.1 – The AJAX web application model

Instead of loading a new page at every step, the browser loads the AJAX engine with the page. The server's response contains data, not presentation; the presentation is applied to that data in the browser. Most of the page does not change. For the web server nothing has changed – it still responds to each request as before.

While JavaScript waits for the server, the user can still type in forms and click buttons. When the server completes its processing, the code updates just the changed part of the page – the user never has to wait. That is the power of asynchronous requests.

Classic (synchronous) model versus AJAX (asynchronous) model
AspectClassic web applicationAJAX web application
RequestEvery action loads a complete pageOnly data is requested in the background
UserWaits while the server processes ("click, wait, refresh")Continues working while the request runs
Data transferredWhole HTML page every timeOnly the needed data (XML/JSON/fragment)
ProcessingAll on the serverValidation, navigation and in-memory editing can be done by the AJAX engine
FeelPage flicker after each actionSmooth, desktop-like

In the classic model every user action is followed by data transmission and server processing, during which the user waits. In the AJAX model, every user action generates a JavaScript call to the AJAX engine; responses that need no server data (validation, some navigation, editing data in memory) are handled by the engine itself, and when it needs the server it communicates asynchronously, without interrupting the user. The model is not bound to a specific data format, programming language or communication mechanism.

The XMLHttpRequest Object

The key to AJAX is the XMLHttpRequest object, used by JavaScript to send HTTP requests, receive the responses and parse them. Apart from XML, it can fetch data in HTML, JSON or plain text format.

The concept was developed by Microsoft for Outlook Web Access 2000 and shipped as an ActiveX control in Internet Explorer 5. Mozilla, Safari and Opera then implemented a native XMLHttpRequest object, and the W3C/WHATWG standardised a common set of properties and methods. Internet Explorer 7 made it a native object as well.

Creating the object in every modern browser is simply:

JavaScript
var xmlRequest = new XMLHttpRequest();

Old Internet Explorer 5 and 6 needed an ActiveX object, so older books detect the browser first:

JavaScript – historical cross-browser code (IE5/IE6)
function getReq() {
    var xmlRequest;
    if (window.XMLHttpRequest) {                 // IE7+, Firefox, Chrome, Safari, Opera
        xmlRequest = new XMLHttpRequest();
    } else if (window.ActiveXObject) {           // IE6, IE5
        try {
            xmlRequest = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                xmlRequest = false;
            }
        }
    }
    return xmlRequest;
}

All current browsers support new XMLHttpRequest() (and the newer fetch()), so the ActiveX branch is no longer needed; it is shown because it appears in much existing code.

Synchronous and asynchronous requests

After creating the object you decide whether the request is synchronous or asynchronous – the third argument of open().

Synchronous (false): after sending the request the script waits until the response arrives – create the object, create the request, send it, hold the processing until the response comes:

JavaScript – synchronous (blocks the page; deprecated on the main thread)
var xmlRequest = new XMLHttpRequest();
xmlRequest.open("GET", "address.xml", false);
xmlRequest.send(null);
var xmlDoc = xmlRequest.responseXML;

Asynchronous (true): set the onreadystatechange event to a handler function, open and send the request, and continue processing; the handler is called as the state changes and checks whether the data is ready:

JavaScript – asynchronous
var xmlRequest = new XMLHttpRequest();
xmlRequest.onreadystatechange = asyncHandler;
xmlRequest.open("GET", "address.xml", true);
xmlRequest.send(null);

function asyncHandler() {
    if (xmlRequest.readyState == 4 && xmlRequest.status == 200) {
        var objXML = xmlRequest.responseXML;
    }
}
XMLHttpRequest properties
PropertyDescription
onreadystatechangeThe event handler called at every change of readyState – usually the asynchronous callback.
readyStateThe state of the request: 0 Uninitialized (open not yet called), 1 Open/Loading (open called, send not yet), 2 Sent (send called, waiting for headers), 3 Receiving/Interactive (part of the data received), 4 Complete/Loaded (all data received).
responseTextThe response as a string (partial during state 3, complete at state 4).
responseXMLThe response as an XML document object (if the content type is XML), usable with DOM methods; null otherwise or before state 4.
statusThe HTTP status code, e.g. 200 (OK), 404 (Not Found), 500 (Server Error).
statusTextThe HTTP status text, e.g. "OK" or "Not Found".
XMLHttpRequest methods
MethodDescription
open(method, url, async, user, password)Prepares the request: method (GET, POST, PUT, DELETE, HEAD), URL, true for asynchronous, optional user and password. Sets readyState to 1.
send([data])Sends the request. For POST, data such as "name=Asha&age=21" is passed here. Sets readyState to 2.
setRequestHeader(label, value)Adds an HTTP header – must be called after open() and before send(), e.g. the Content-Type of POST data.
abort()Cancels the current request and resets the object.
getResponseHeader(name)Returns the value of one response header.
getAllResponseHeaders()Returns all response headers as one string.
XMLHttpRequest and IFrames

Before XMLHttpRequest became common, IFrames (inline frames) were used to load content from another page into part of a page without reloading the whole page – news clips, calendars, weather forecasts:

HTML
<iframe src="date.php" name="my_iframe" frameborder="0" width="500" height="200"
        scrolling="yes"></iframe>

The only required attribute is src (the page shown in the frame); name targets the frame, width/height give its size, scrolling (yes, no, auto) allows scroll bars and frameborder the border. IFrames load whole pages and give little control over the data, while XMLHttpRequest exchanges only data and lets JavaScript decide how to display it – which is why AJAX uses XMLHttpRequest.

Example 1 – Getting Data from PHP

A button asks the server for its current time without reloading the page.

servertime.php – the server side
<?php
date_default_timezone_set("Asia/Kolkata");
echo "Server time is " . date("h:i:s A") . " on " . date("d-m-Y");
time.html – the page
<html>
<body style="font-family:Arial;font-size:13px">
<h3>AJAX demo</h3>
<button id="btn" onclick="loadTime()">Get server time</button>
<p id="result">The answer will appear here.</p>
<p>This paragraph is never reloaded.</p>
<script>
function loadTime() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            document.getElementById("result").innerHTML = xhr.responseText;
        }
    };
    xhr.open("GET", "servertime.php", true);
    xhr.send();
}
</script>
</body>
</html>
OUTPUT browser · time.html after clicking the button (no page reload)
Browser output
Example 2 – Live Search with PHP and MySQLi

As the user types, the names of matching students are fetched from the database and shown under the box.

suggest.php – returns matching names
<?php
$q = $_GET["q"] ?? "";
if (strlen($q) == 0) exit;
$conn = new mysqli("localhost", "root", "", "phpbook");
$result = $conn->execute_query(
    "SELECT name, city FROM students WHERE name LIKE ? ORDER BY name", ["%$q%"]);
if ($result->num_rows == 0) {
    echo "No suggestion";
}
foreach ($result as $row) {
    echo htmlspecialchars($row["name"]) . " <small>(" . htmlspecialchars($row["city"]) . ")</small><br>";
}
livesearch.html
<html>
<body style="font-family:Arial;font-size:13px">
Student name: <input type="text" id="q" onkeyup="showHint(this.value)">
<div id="hint" style="border:1px solid #aaa;padding:4px;margin-top:4px;width:260px">
  Suggestions:
</div>
<script>
function showHint(str) {
    if (str.length == 0) {
        document.getElementById("hint").innerHTML = "";
        return;
    }
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById("hint").innerHTML = this.responseText;
        }
    };
    xhr.open("GET", "suggest.php?q=" + encodeURIComponent(str), true);
    xhr.send();
}
</script>
</body>
</html>
OUTPUT browser · livesearch.html after typing “an”
Browser output
Example 3 – Sending a Form with POST

For POST requests the data is passed to send() and the request needs a Content-Type header, set with setRequestHeader():

savefeedback.php
<?php
$conn = new mysqli("localhost", "root", "", "phpbook");
$name = trim($_POST["name"] ?? "");
$msg  = trim($_POST["message"] ?? "");
if ($name === "" || $msg === "") {
    http_response_code(400);
    echo "Please fill in both fields.";
    exit;
}
$conn->execute_query("INSERT INTO feedback (name, message) VALUES (?, ?)", [$name, $msg]);
echo "Thank you, " . htmlspecialchars($name) . "! Feedback #" . $conn->insert_id . " saved.";
feedback.html
<html>
<body style="font-family:Arial;font-size:13px">
Name: <input id="name"><br>
Message: <input id="message" size="30"><br>
<button id="send" onclick="sendFeedback()">Send</button>
<p id="status" style="color:green"></p>
<script>
function sendFeedback() {
    var data = "name=" + encodeURIComponent(document.getElementById("name").value)
             + "&message=" + encodeURIComponent(document.getElementById("message").value);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "savefeedback.php", true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            document.getElementById("status").innerHTML =
                xhr.responseText + " (HTTP " + xhr.status + " " + xhr.statusText + ")";
        }
    };
    xhr.send(data);
}
</script>
</body>
</html>
OUTPUT browser · feedback.html after clicking Send
Browser output
Example 4 – Reading an XML Response

When the server sends XML (Content-Type: text/xml or application/xml), responseXML contains a parsed document that can be read with DOM methods:

coursesxml.php – sends XML
<?php
header("Content-Type: application/xml; charset=UTF-8");
$conn = new mysqli("localhost", "root", "", "phpbook");
$xml = new SimpleXMLElement("<courses/>");
foreach ($conn->query("SELECT course_name, fee FROM courses") as $r) {
    $c = $xml->addChild("course");
    $c->addChild("name", htmlspecialchars($r["course_name"]));
    $c->addChild("fee", $r["fee"]);
}
echo $xml->asXML();
xmlclient.html
<html>
<body style="font-family:Arial;font-size:13px">
<button id="load" onclick="loadCourses()">Load courses</button>
<table id="tbl" border="1" cellpadding="4" style="border-collapse:collapse;margin-top:6px"></table>
<script>
function loadCourses() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            var doc = xhr.responseXML;
            var courses = doc.getElementsByTagName("course");
            var html = "<tr><th>Course</th><th>Fee</th></tr>";
            for (var i = 0; i < courses.length; i++) {
                html += "<tr><td>" + courses[i].getElementsByTagName("name")[0].textContent
                      + "</td><td>" + courses[i].getElementsByTagName("fee")[0].textContent + "</td></tr>";
            }
            document.getElementById("tbl").innerHTML = html;
        }
    };
    xhr.open("GET", "coursesxml.php", true);
    xhr.send();
}
</script>
</body>
</html>
OUTPUT browser · xmlclient.html after clicking Load courses
Browser output
Introduction to JSON

AJAX makes server responses faster by letting client-side scripts retrieve only the required data instead of a complete page. Such responses were originally XML, which then had to be parsed in JavaScript – making the JavaScript code complicated. The idea of JSON (JavaScript Object Notation) is to send the response as a data structure that JavaScript can use directly.

Advantages of JSON
  • A lightweight data-interchange format.
  • Easy for humans to read and write.
  • Easy for machines to parse and generate.
  • Parsed in JavaScript with JSON.parse(). (Old code used eval(), which is unsafe – never use it on server data.)
  • Supported by practically every language – ActionScript, C, C#, ColdFusion, Java, JavaScript, ML, Objective CAML, Perl, PHP, Python, Rebol, Ruby, Lua and many more.
JSON syntax

JSON syntax is close to the C family of languages:

  • An object starts with { and ends with } and contains members – "string" : value pairs separated by commas.
  • An array is written between [ and ], with elements – values separated by commas.
  • A value can be a string (in double quotes), a number, an object, an array, true, false or null.

The same menu in JSON and in XML:

JSON
{"menu": {
    "id": "file",
    "value": "File",
    "popup": {
        "menuitem": [
            {"value": "New",   "onclick": "CreateNewDoc()"},
            {"value": "Open",  "onclick": "OpenDoc()"},
            {"value": "Close", "onclick": "CloseDoc()"}
        ]
    }
}}
XML
<menu id="file" value="File">
  <popup>
    <menuitem value="New" onclick="CreateNewDoc()" />
    <menuitem value="Open" onclick="OpenDoc()" />
    <menuitem value="Close" onclick="CloseDoc()" />
  </popup>
</menu>
JSON in PHP

PHP converts between PHP values and JSON with json_encode() and json_decode():

File: htdocs/phpbook/ch39/json.php
<?php
$student = ["roll" => 101, "name" => "Asha", "marks" => [82, 75], "passed" => true, "phone" => null];
$json = json_encode($student);
echo "json_encode: $json<br>";
echo "Pretty:<pre>" . json_encode($student, JSON_PRETTY_PRINT) . "</pre>";
$text = '{"city":"Bhopal","pin":462011,"tags":["lakes","capital"]}';
$obj = json_decode($text);                 // object
$arr = json_decode($text, true);           // associative array
echo "json_decode as object: $obj->city, " . $obj->tags[0] . "<br>";
echo "json_decode as array: {$arr['pin']}<br>";
json_decode('{bad json}');
echo "Invalid JSON: " . json_last_error_msg();
?>
OUTPUT browser · http://localhost/phpbook/ch39/json.php
json_encode: {"roll":101,"name":"Asha","marks":[82,75],"passed":true,"phone":null}
Pretty:
{
    "roll": 101,
    "name": "Asha",
    "marks": [
        82,
        75
    ],
    "passed": true,
    "phone": null
}
json_decode as object: Bhopal, lakes
json_decode as array: 462011
Invalid JSON: Syntax error
Example 5 – A JSON API with fetch()

Modern JavaScript offers fetch(), a simpler, promise-based replacement for XMLHttpRequest. The PHP script sends JSON with the header Content-Type: application/json:

api_students.php – a small JSON API
<?php
header("Content-Type: application/json");
$conn = new mysqli("localhost", "root", "", "phpbook");
$city = $_GET["city"] ?? "";
$rows = $conn->execute_query(
    "SELECT roll, name, city FROM students WHERE city LIKE ? ORDER BY roll", ["%$city%"]
)->fetch_all(MYSQLI_ASSOC);
echo json_encode(["count" => count($rows), "students" => $rows]);
OUTPUT browser · http://localhost/phpbook/ch39/api_students.php?city=Indore
{"count":2,"students":[{"roll":102,"name":"Ravi Kumar","city":"Indore"},{"roll":105,"name":"Kiran Patel","city":"Indore"}]}
fetchdemo.html
<html>
<head><meta charset="utf-8"></head>
<body style="font-family:Arial;font-size:13px">
City:
<select id="city" onchange="load(this.value)">
  <option value="">All</option><option>Bhopal</option><option>Indore</option>
</select>
<ul id="list"></ul>
<script>
async function load(city) {
    const response = await fetch("api_students.php?city=" + encodeURIComponent(city));
    const data = await response.json();             // parses the JSON
    let html = "<b>" + data.count + " student(s)</b>";
    for (const s of data.students) {
        html += "<li>" + s.roll + " – " + s.name + " (" + s.city + ")</li>";
    }
    document.getElementById("list").innerHTML = html;
}
load("");
</script>
</body>
</html>
OUTPUT browser · fetchdemo.html after choosing Bhopal
Browser output
Key Takeaways
  • AJAX = Asynchronous JavaScript And XML – a technique that updates part of a page by exchanging data with the server in the background.
  • The AJAX engine sits between the user and the server; users keep working while requests run.
  • XMLHttpRequest: open(method, url, async), setRequestHeader(), send(data), onreadystatechange, readyState (0–4), status, responseText, responseXML.
  • Asynchronous requests (true) do not block the page; synchronous ones do.
  • PHP returns plain text, HTML fragments, XML or JSON; use prepared statements in AJAX back ends too.
  • JSON is lighter than XML: json_encode()/json_decode() in PHP, JSON.parse()/response.json() in JavaScript; fetch() is the modern alternative to XMLHttpRequest.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch39 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : Asynchronous JavaScript And XML – a technique that uses JavaScript, the DOM, XMLHttpRequest and XML/JSON to exchange data with the server in the background and update parts of a page without reloading it.

Answer : Jesse James Garrett of Adaptive Path, in 2005.

Answer : The JavaScript layer loaded with the page that sits between the user interface and the server; it sends requests asynchronously, handles some processing itself and updates the page.

Answer : In the classic model each action loads a whole new page and the user waits; in the AJAX model only data is requested in the background, the user keeps working, and only the changed part of the page is updated.

Answer : A JavaScript object (originally an ActiveX control in IE5) used to send HTTP requests to the server and receive the responses as text or XML without reloading the page.

Answer : In a synchronous request (open(..., false)) the script waits until the response arrives, freezing the page; in an asynchronous request (open(..., true)) the script continues and a handler is called when the response is ready.

Answer : 0 uninitialized, 1 open (open() called), 2 sent (send() called), 3 receiving (part of the response received), 4 complete (whole response received).

Answer : responseText returns the response as a string; responseXML returns it as a parsed XML document object (only if the response is XML), which can be read with DOM methods.

Answer : The HTTP status code of the response, e.g. 200 for OK or 404 for Not Found; statusText contains the matching text.

Answer : open(method, url, async, user, password): the HTTP method (GET, POST …), the URL of the server script, true for asynchronous or false for synchronous, and an optional user name and password.

Answer : To tell the server the format of the data sent with send(), e.g. setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); it must be called after open() and before send().

Answer : IFrames loaded another page into part of the current page without a full reload. XMLHttpRequest transfers only data and lets JavaScript control exactly how and where it is displayed.

Answer : JavaScript Object Notation – a lightweight text format of objects {}, arrays [] and values. It is smaller than XML and can be turned into JavaScript objects directly with JSON.parse(), which keeps client code simple.

Answer : json_encode() converts arrays/objects to a JSON string; json_decode() converts JSON into a PHP object (or an associative array with the second argument true). json_last_error_msg() reports errors.

Answer : A modern, promise-based JavaScript API for HTTP requests – a simpler replacement for XMLHttpRequest, e.g. const data = await (await fetch(url)).json();
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which readyState value means the response is complete?

Show Answer

Correct Answer : D. 4
4 = Complete/Loaded.

Q2. The third argument of xhr.open("GET", url, true) makes the request:

Show Answer

Correct Answer : C. Asynchronous
true = asynchronous.

Q3. Which property returns the server response as a string?

Show Answer

Correct Answer : B. responseText
responseText is the text of the response.

Q4. Which PHP function turns an array into JSON?

Show Answer

Correct Answer : C. json_encode()
json_encode() produces a JSON string.

Q5. AJAX was originally made possible by an object first shipped in:

Show Answer

Correct Answer : B. Internet Explorer 5
XMLHttpRequest began as an ActiveX control in IE5.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. Garrett, J. J. (2005). Ajax: A New Approach to Web Applications. Adaptive Path.
  2. WHATWG. (n.d.). XMLHttpRequest Standard. https://xhr.spec.whatwg.org/
  3. MDN contributors. (n.d.). Using the Fetch API. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
  4. ECMA International. (2017). ECMA-404: The JSON Data Interchange Syntax. https://www.ecma-international.org/publications-and-standards/standards/ecma-404/
  5. The PHP Group. (n.d.). PHP Manual – JSON Functions. https://www.php.net/manual/en/ref.json.php