The live example sends a URL-encoded search term to ajax-search-demock.php. The PHP endpoint validates input and runs a prepared query against the student table. The basic select-list response is HTML with database values escaped before output; the separate datalist demo requests JSON.
Use the first copyable example with the search input and results container in the live demo below. The next examples explain the XMLHttpRequest equivalent and the PHP query. Always check responses and abort outdated search requests.
// Use this on the live select-list demo with #keyword and #displayDiv.
const input = document.getElementById('keyword');
const results = document.getElementById('displayDiv');
let pendingRequest;
input.addEventListener('input', async () => {
if (pendingRequest) pendingRequest.abort();
const term = input.value.trim();
if (!term) { results.replaceChildren(); return; }
pendingRequest = new AbortController();
const request = pendingRequest;
try {
const response = await fetch('ajax-search-demock.php?txt=' + encodeURIComponent(term),
{ signal: request.signal });
if (!response.ok) throw new Error('Search failed');
const safeHtml = await response.text();
if (pendingRequest === request) results.innerHTML = safeHtml;
} catch (error) {
if (error.name !== 'AbortError') results.textContent = 'Search unavailable.';
}
});
Use AJAX to search database records as the user types. The advantage of this is we are not waiting for the full keyword to be typed and then submit to get the matching records. As you type, the browser sends the search text to PHP over AJAX and the result is displayed below the text box.
fetch() example is shown first; the XMLHttpRequest form demonstrates the same request without fetch().
ajax-search-demo.php
<!-- Main markup for the XMLHttpRequest version -->
<label for="keyword">Student name</label>
<input type="search" id="keyword" autocomplete="off">
<div id="displayDiv" aria-live="polite"></div>
<script>
const input = document.getElementById('keyword');
let request;
input.addEventListener('input', () => {
if (request) request.abort();
const term = input.value.trim();
if (!term) { document.getElementById('displayDiv').textContent = ''; return; }
const current = new XMLHttpRequest();
request = current;
current.open('GET', 'ajax-search-demock.php?txt=' + encodeURIComponent(term));
current.onload = () => {
if (request !== current) return;
if (current.status === 200) {
// The PHP endpoint escapes database values before producing select markup.
document.getElementById('displayDiv').innerHTML = current.responseText;
}
};
current.send();
});
</script>
LIKE query with a bound parameter and escapes database text in the returned HTML. The complete endpoint also checks database errors and can return JSON for the datalist demo. ajax-search-demock.php (abbreviated example; the downloadable endpoint also supports JSON for the datalist demo)
<?php
header('Content-Type: text/html; charset=UTF-8');
$term = $_GET['txt'] ?? '';
if (!is_string($term) || strlen($term) > 60 ||
!preg_match('/^[\p{L}\p{M}0-9 .\x27-]+$/u', trim($term))) {
http_response_code(400);
exit('Invalid search term.');
}
require '../include/z_db1.php'; // PDO connection is provided as $dbo.
$stmt = $dbo->prepare('SELECT name, id FROM student WHERE name LIKE :term ORDER BY name LIMIT 15');
$stmt->execute(['term' => '%' . trim($term) . '%']);
echo '<select id="search-results" size="10" aria-label="Matching students">';
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
$id = htmlspecialchars((string) $row['id'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
$name = htmlspecialchars((string) $row['name'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo '<option value="' . $id . '">' . $name . ' => ' . $id . '</option>';
}
echo '</select>';
?>
Try the datalist autocomplete demo. It requests format=json from the same endpoint and creates each <option> with DOM methods, so returned names are treated as text rather than HTML.
const response = await fetch(
'ajax-search-demock.php?format=json&txt=' + encodeURIComponent(term),
{ headers: { Accept: 'application/json' } }
);
if (!response.ok) throw new Error('Search failed');
const names = await response.json();
const datalist = document.getElementById('student');
datalist.replaceChildren();
for (const name of names) {
const option = document.createElement('option');
option.value = String(name);
datalist.append(option);
}
As the user types, the browser sends the search term to the PHP endpoint and uses the matching names as options of the datalist. You can also review the HTML datalist basics.
select title from TABLE where title like '%plus2net%' or title like '%demo%'
So we need to extend our above query depending on the number of words used for searching.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.
| John | 24-08-2013 |
| Awesome tutorial... Keep posting Ajax tutorials.. | |
| sopha | 23-10-2013 |
| I like your website | |
| Chinthaka | 01-06-2014 |
| Wow fantastic !!! 100% working | |
| Arshad | 28-09-2014 |
| Always Rocking Plus2net.com! My PHP site was created by the help of Plus2net! Thank you! so much.. | |
| John | 12-07-2015 |
| Fatal error: Class 'PDO' not found | |
| smo1234 | 17-07-2015 |
| Inside config.php file read the database connection part. | |
| Imran | 09-08-2018 |
| This works good but for very much low records in table. I have inserted 0.2 Million records in table and then i used this technique believe me my site got stuck after few requests. Do you have any solutions for big data searching with ajax. | |