PHP and AJAX
At our company, we understand the importance of creating dynamic and responsive web applications. One of the key tools for achieving this is PHP AJAX. In this
This chapter explains how to combine AJAX (in the browser) with PHP (on the server) so a page can talk to the server in the background and update only the part that changed — no full reload. You will build a complete, working example, see how to read the request in PHP and return JSON, and learn the security and error-handling rules that real applications need.
What is PHP AJAX?
AJAX stands for Asynchronous JavaScript and XML. Despite the name, modern AJAX rarely uses XML — it sends and receives JSON, because JSON maps directly onto JavaScript objects and PHP arrays. The key word is asynchronous: the browser fires a request and keeps running. When the server replies, a callback updates the page. The user never sees a blank reloading screen.
"PHP AJAX" is just this pattern with PHP as the server side: JavaScript sends the request, a PHP script handles it (often querying a database), and PHP echoes JSON back for JavaScript to render.
Common uses:
- Live search / autocomplete — suggestions appear as you type.
- Inline form validation — check a username or email before the user submits.
- Like / vote / favorite buttons — update a counter without leaving the page.
- Infinite scroll and "load more" — fetch the next page of results on demand.
How an AJAX request flows
A single round trip always follows the same four steps:
- Event — the user types, clicks, or submits. JavaScript catches the event.
- Request — JavaScript sends an HTTP request to a PHP endpoint (with
fetchorXMLHttpRequest). - Server work — PHP reads the input from
$_GET,$_POST, or the raw request body, does its work (e.g. a database query), andechos a JSON response. - Update — JavaScript receives the JSON, parses it, and updates the DOM.
The browser is the client; the PHP script is the server. They only exchange small pieces of data, which is why AJAX feels instant compared to reloading a whole page.
Sending the request: fetch vs XMLHttpRequest
XMLHttpRequest (XHR) is the original AJAX API. fetch is the modern, promise-based replacement — shorter, easier to read, and built into every current browser. Use fetch for new code; you only need XHR when supporting very old browsers.
// Modern: fetch returns a Promise
fetch('endpoint.php')
.then(res => res.json()) // parse the JSON body
.then(data => console.log(data));
// Legacy: the equivalent with XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', 'endpoint.php');
xhr.onload = () => console.log(JSON.parse(xhr.responseText));
xhr.send();Reading the request and replying with JSON in PHP
How PHP reads the incoming data depends on how JavaScript sent it:
| JavaScript sends | PHP reads it with |
|---|---|
URL query string (?q=...) | $_GET['q'] |
FormData (a real form) | $_POST['field'] |
JSON.stringify(obj) body | json_decode(file_get_contents('php://input'), true) |
Whatever the input, the reply should be JSON with the correct header so the browser parses it correctly:
<?php
header('Content-Type: application/json');
echo json_encode(['status' => 'success', 'value' => 42]);The header() line tells the browser the body is JSON. json_encode() turns the PHP array into a JSON string. See PHP JSON and json_encode() for the full reference.
A complete example: live search suggestions
This is a full, working autocomplete: type in the box, JavaScript queries search.php, and PHP returns matching items as JSON.
HTML + JavaScript (the page):
<input id="searchInput" type="text" placeholder="Search fruit…" autocomplete="off">
<ul id="results"></ul>
<script>
const input = document.getElementById('searchInput');
const list = document.getElementById('results');
let timer;
input.addEventListener('input', () => {
// Debounce: wait until the user pauses typing (avoids a request per keystroke)
clearTimeout(timer);
timer = setTimeout(() => {
const query = input.value.trim();
if (!query) { list.innerHTML = ''; return; }
fetch(`search.php?q=${encodeURIComponent(query)}`)
.then(res => res.json())
.then(data => {
list.innerHTML = data.suggestions
.map(item => `<li>${item}</li>`)
.join('');
})
.catch(() => { list.innerHTML = '<li>Search failed</li>'; });
}, 250);
});
</script>PHP (search.php):
<?php
header('Content-Type: application/json');
// 1. Read and sanitise the input
$query = trim($_GET['q'] ?? '');
// 2. Do the work. In real code this is a *prepared* SQL query — see the note below.
$fruits = ['apple', 'apricot', 'banana', 'cherry', 'grape', 'mango'];
$matches = array_values(array_filter(
$fruits,
fn($fruit) => str_contains($fruit, strtolower($query))
));
// 3. Reply with JSON
echo json_encode(['suggestions' => $matches]);Type ap and the list shows every fruit containing those letters — apple, apricot, and grape — and the page never reloads. To pull suggestions from a database instead of the in-memory array, use a prepared statement as shown in AJAX and MySQL Database.
Always use prepared statements. Never drop
$_GET['q']straight into an SQL string — that is a SQL-injection hole. Use bound parameters (see PHP MySQLi).
Inline form validation
Validate a field on the server before the user submits the whole form. The same PHP rules that protect submission can be reused for the AJAX check.
const form = document.getElementById('myForm');
form.addEventListener('submit', (e) => {
e.preventDefault(); // stop the normal page reload
fetch('validate.php', {
method: 'POST',
body: new FormData(form) // sends fields as $_POST
})
.then(res => res.json())
.then(data => {
if (data.valid) form.submit();
else console.log(data.errors);
});
});<?php
header('Content-Type: application/json');
$errors = [];
$email = trim($_POST['email'] ?? '');
if ($email === '') {
$errors[] = 'Email is required';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format';
}
echo json_encode(['valid' => empty($errors), 'errors' => $errors]);new FormData(form) collects every field, so PHP reads them from $_POST. For deeper form coverage see PHP Form Validation and PHP $_GET / $_POST superglobals.
Common gotchas
- CORS. A request to a different origin (domain, port, or scheme) is blocked unless the PHP server sends
Access-Control-Allow-Origin. Same-origin requests need nothing. - Set the JSON header. Forgetting
header('Content-Type: application/json')still works withres.json(), but it breaks tools that rely on the content type. Always set it. - Handle errors. Network failures and 500 responses must be caught — add a
.catch()and checkres.ok, or the UI silently does nothing. - Debounce live requests. Without the
setTimeoutdebounce above, every keystroke fires a request and hammers the server. - Escape output you inject into the DOM. Inserting raw server text with
innerHTMLcan introduce XSS; escape or usetextContentfor untrusted data.
Summary
PHP AJAX lets a page exchange small amounts of data with the server in the background and update in place. JavaScript sends the request with fetch, PHP reads it from $_GET/$_POST/php://input, does its work, and returns JSON via json_encode(). Keep input on prepared statements, set the JSON header, and always handle the error path.
Next steps: connect AJAX to a real database in AJAX and MySQL, and learn the response format in depth in PHP JSON.