AJAX Intro
What Is AJAX? In simple terms: Normally, when you click a link or submit a form, the browser loads a completely new page. AJAX lets a web page talk to the server in the background and update only part
What Is AJAX?
In simple terms: Normally, when you click a link or submit a form, the browser loads a completely new page. AJAX lets a web page talk to the server in the background and update only part of the page — showing search suggestions as you type, checking if a username is available, adding an item to the cart, or loading more comments — without a full page reload.
Technically: AJAX originally stood for Asynchronous JavaScript and XML. JavaScript in the browser sends an HTTP request to the server, continues running while waiting (asynchronously), and updates the page (the DOM) when the response arrives. Today, requests are usually sent with the Fetch API (fetch()), and responses are mostly JSON rather than XML — but the name AJAX remains. On the server side, a PHP script simply receives a normal HTTP request and returns data.
Full Page Load vs AJAX
Traditional request: AJAX request:
Browser ──request──► PHP JavaScript ──fetch()──► PHP endpoint
Browser ◄──complete HTML page── PHP JavaScript ◄──JSON data── PHP
(whole page reloads) (JavaScript updates one part of the page)
| Full Page Load | AJAX | |
|---|---|---|
| Data transferred | The whole page | Only the data needed |
| User experience | Page flickers, scroll position resets | Smooth, partial updates |
| Server output | HTML page | Usually JSON (sometimes HTML fragments or XML) |
| Works without JavaScript | Yes | No — provide a fallback for essential features |
How an AJAX Request Works
1. An event happens the user clicks a button or types in a field
2. JavaScript sends request fetch('/api/server-time.php')
3. PHP processes it reads parameters, queries the database, returns JSON
4. JavaScript receives data await response.json()
5. The page is updated element.textContent = data.time
A First Example
The PHP Endpoint: api/server-time.php
<?php
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
$now = new DateTimeImmutable('now', new DateTimeZone('Asia/Kolkata'));
echo json_encode([
'time' => $now->format('H:i:s'),
'date' => $now->format('l, d F Y'),
'timezone' => $now->getTimezone()->getName(),
], JSON_THROW_ON_ERROR);
Response (example)
{"time":"14:05:09","date":"Thursday, 15 October 2026","timezone":"Asia/Kolkata"}
You can open api/server-time.php directly in the browser to see this JSON — an AJAX endpoint is an ordinary PHP script that outputs data instead of a page.
The Page: index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Server Time</title>
</head>
<body>
<button id="refresh" type="button">Get server time</button>
<p id="result" aria-live="polite">Click the button.</p>
<script>
const button = document.getElementById('refresh');
const result = document.getElementById('result');
button.addEventListener('click', async () => {
result.textContent = 'Loading…';
try {
const response = await fetch('api/server-time.php');
if (!response.ok) {
throw new Error(`Server responded with ${response.status}`);
}
const data = await response.json();
result.textContent = `${data.date}, ${data.time} (${data.timezone})`;
} catch (error) {
result.textContent = 'Could not load the time. Please try again.';
console.error(error);
}
});
</script>
</body>
</html>
How It Works
- Clicking the button runs an
asyncfunction. fetch()sends a GET request to the PHP endpoint.awaitpauses this function (not the whole page) until the response arrives.response.okistruefor HTTP status codes 200–299.fetch()does not throw for 404 or 500 responses, so the status must be checked explicitly.response.json()parses the JSON body into a JavaScript object.- Only the paragraph's text changes; the rest of the page stays as it is.
textContent(instead ofinnerHTML) inserts the data as plain text, which prevents XSS if a value ever contains HTML.aria-live="polite"makes screen readers announce the updated text.
The Older Way: XMLHttpRequest
Before fetch() (supported in all modern browsers), AJAX used the XMLHttpRequest object:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'api/server-time.php');
xhr.onload = () => {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
document.getElementById('result').textContent = data.time;
}
};
xhr.send();
You will see it in older code and in libraries such as jQuery's $.ajax(). For new code, fetch() with async/await is simpler and more readable.
What the Server Side Must Do
An AJAX endpoint follows the same rules as any PHP page — plus a few specific to data APIs:
| Responsibility | How |
|---|---|
| Declare the response type | Content-Type: application/json; charset=utf-8 |
| Return meaningful status codes | 200 success, 400/422 invalid input, 401/403 not allowed, 404 not found, 500 errors |
| Validate all input | Parameters from AJAX requests are user input, just like form fields |
| Check authentication and permissions | Use the session as for normal pages; never trust a user ID sent by JavaScript |
| Protect state-changing requests | Use POST (or PUT/PATCH/DELETE) with a CSRF token (see CSRF Protection) |
| Output only data | No HTML layout, no stray whitespace or warnings before the JSON |
Same-Origin Policy and CORS
By default, browsers only allow JavaScript to read responses from the same origin (same scheme, host, and port) as the page. If a page on https://app.example.com calls an API on https://api.example.com, the API must send CORS headers (such as Access-Control-Allow-Origin: https://app.example.com). Never answer with Access-Control-Allow-Origin: * for endpoints that use cookies or return private data.
AJAX Lessons in This Section
| Lesson | Topic |
|---|---|
| AJAX PHP | Writing PHP endpoints and sending GET and POST requests |
| AJAX Database | Loading database records without reloading the page |
| AJAX XML | Exchanging XML instead of JSON |
| AJAX Live Search | Search suggestions while typing |
| AJAX Poll | A voting widget that updates results instantly |
| AJAX with JSON | Structured JSON APIs and error handling |
Common Mistakes
Ignoring HTTP Error Statuses
Effect: fetch() resolves for 404 and 500 responses; the code then fails to parse an error page as JSON.
Fix: Check response.ok before reading the data.
Inserting Responses With innerHTML
Effect: XSS vulnerabilities if data contains HTML.
Fix: Use textContent, or build elements with DOM methods.
Stray Output Before JSON
Effect: Warnings, whitespace, or a BOM before the JSON make response.json() fail.
Fix: Log errors instead of displaying them; omit closing ?> tags in PHP files.
Making Essential Features Depend Only on JavaScript
Effect: Features break when JavaScript fails or is blocked.
Fix: Use progressive enhancement: a normal form or link works without JavaScript, and AJAX improves it.
Best Practices
- Use
fetch()withasync/awaitand handle network errors and HTTP status codes. - Return JSON with a correct
Content-Typeand meaningful status codes. - Treat every AJAX parameter as untrusted input and check permissions on the server.
- Update the page with
textContentor DOM methods to avoid XSS. - Inspect requests and responses in the browser's developer tools (Network tab) while developing.
Official reference: https://www.php.net/manual/en/tutorial.php