Chapter 27: AJAX PHP
AJAX + PHP example, explained as if I am your patient teacher sitting next to you.
We will go extremely slowly, step by step, with complete explanations, reasoning, common mistakes, multiple variations, and several complete runnable examples.
Goal of this lesson
We will build realistic AJAX + PHP examples that you can copy-paste and run on your own computer.
We will create:
- GET example – fetching data from PHP without page reload
- POST example – sending form data to PHP and getting response
- Search / autocomplete style example (very common real-world pattern)
- Loading state + error handling (professional look)
- JSON response (modern standard – what you should use today)
Before we start – what you need on your computer
- XAMPP / WAMP / MAMP (or any local server with PHP)
- Create a folder inside htdocs (XAMPP) → example name: ajax-php-demo
- Put all files inside this folder
- Access via browser: http://localhost/ajax-php-demo/
Example 1 – Basic GET Request (Fetch data from PHP)
File 1: index.html (the frontend)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AJAX + PHP – GET Example</title> <style> body { font-family: Arial, Helvetica, sans-serif; margin: 40px; background: #f9f9f9; line-height: 1.6; } h1 { color: #2c3e50; } button { padding: 12px 24px; font-size: 16px; margin: 10px 15px 10px 0; cursor: pointer; background: #3498db; color: white; border: none; border-radius: 5px; } button:hover { background: #2980b9; } #result { margin-top: 30px; padding: 25px; background: white; border: 1px solid #ddd; border-radius: 8px; min-height: 120px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .loading { color: #7f8c8d; font-style: italic; } .error { color: #c0392b; font-weight: bold; } </style> </head> <body> <h1>AJAX + PHP – Classic GET Example</h1> <p>Click any button – only the result area updates (no page reload)</p> <button onclick="fetchData('hello')">1. Say Hello</button> <button onclick="fetchData('time')">2. Get Server Time</button> <button onclick="fetchData('random')">3. Random Number (1–100)</button> <div id="result">Click any button above to see result...</div> <script> function fetchData(type) { const resultDiv = document.getElementById('result'); resultDiv.className = 'loading'; resultDiv.innerHTML = 'Loading... Please wait...'; // Create the request object const xhr = new XMLHttpRequest(); // Build URL with parameter let url = `server-get.php?action=${type}`; xhr.open("GET", url, true); // true = asynchronous xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300) { // Success resultDiv.className = ''; resultDiv.innerHTML = ` <strong>Server Response:</strong><br><br> <pre style="background:#f4f4f4; padding:15px; border-radius:6px;"> ${xhr.responseText} </pre> `; } else { // Server error (404, 500, etc.) resultDiv.className = 'error'; resultDiv.innerHTML = ` Error ${xhr.status} ${xhr.statusText}<br> ${xhr.responseText ? '<br>Server message:<br>' + xhr.responseText : ''} `; } }; xhr.onerror = function() { resultDiv.className = 'error'; resultDiv.innerHTML = 'Network error – cannot connect to server'; }; xhr.send(); } </script> </body> </html> |
File 2: server-get.php (the backend – PHP)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?php // Very important: tell browser this is plain text response header('Content-Type: text/plain; charset=utf-8'); // Prevent caching so we always get fresh data header('Cache-Control: no-cache, must-revalidate'); // Get the action parameter $action = isset($_GET['action']) ? $_GET['action'] : ''; // Simple switch – real application would use database switch ($action) { case 'hello': echo "Hello from the server!\n"; echo "This message came via AJAX GET request.\n"; echo "Current time: " . date('d-m-Y H:i:s'); break; case 'time': echo "Current server time:\n"; echo date('d-m-Y H:i:s') . "\n"; echo "Timezone: " . date_default_timezone_get(); break; case 'random': $number = rand(1, 100); echo "Random number generated by server: $number\n"; echo "Generated at: " . date('H:i:s'); break; default: http_response_code(400); echo "Invalid action parameter.\n"; echo "Use ?action=hello or ?action=time or ?action=random"; break; } |
How to run this example
- Put both files in the same folder (ajax-php-demo)
- Start XAMPP / WAMP
- Open browser: http://localhost/ajax-php-demo/index.html
- Click buttons → see magic!
4. Example 2 – POST Request (Sending Form Data to PHP)
File: index-post.html
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>AJAX POST + PHP</title> <style> body { font-family: Arial; margin: 40px; } form { max-width: 500px; } label { display: block; margin: 15px 0 5px; font-weight: bold; } input, textarea { width: 100%; padding: 10px; font-size: 16px; box-sizing: border-box; } button { margin-top: 20px; padding: 12px 30px; background: #27ae60; color: white; border: none; border-radius: 5px; cursor: pointer; } #result { margin-top: 40px; padding: 20px; background: #ecf0f1; border: 1px solid #bdc3c7; border-radius: 6px; min-height: 100px; } </style> </head> <body> <h1>AJAX POST to PHP – Contact Form Example</h1> <form id="contactForm"> <label for="name">Your Name:</label> <input type="text" id="name" name="name" required> <label for="email">Email:</label> <input type="email" id="email" name="email" required> <label for="message">Message:</label> <textarea id="message" name="message" rows="5" required></textarea> <button type="submit">Send Message</button> </form> <div id="result"></div> <script> document.getElementById('contactForm').addEventListener('submit', function(e) { e.preventDefault(); // Stop normal form submit const resultDiv = document.getElementById('result'); resultDiv.innerHTML = '<strong>Sending message...</strong>'; // Collect form data const formData = new FormData(this); const xhr = new XMLHttpRequest(); xhr.open('POST', 'server-post.php', true); xhr.onload = function() { if (xhr.status >= 200 && xhr.status < 300) { resultDiv.innerHTML = ` <strong style="color: green;">Success!</strong><br><br> ${xhr.responseText.replace(/\n/g, '<br>')} `; } else { resultDiv.innerHTML = ` <strong style="color: red;">Error ${xhr.status}</strong><br> ${xhr.responseText || 'Server error'} `; } }; xhr.onerror = function() { resultDiv.innerHTML = '<strong style="color: red;">Network error – cannot connect</strong>'; }; xhr.send(formData); }); </script> </body> </html> |
File: server-post.php
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php header('Content-Type: text/plain; charset=utf-8'); // Very important: never trust client data in real projects! $name = trim($_POST['name'] ?? ''); $email = trim($_POST['email'] ?? ''); $message = trim($_POST['message'] ?? ''); if (empty($name) || empty($email) || empty($message)) { http_response_code(400); echo "Error: All fields are required."; exit; } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { http_response_code(400); echo "Error: Invalid email format."; exit; } // In real project: save to database, send email, etc. // Here we just simulate success sleep(1); // fake delay echo "Thank you, $name!\n\n"; echo "We received your message:\n"; echo $message . "\n\n"; echo "Email: $email\n"; echo "Message received at: " . date('d-m-Y H:i:s'); |
Summary – What we learned in this lesson
- GET – fetching data (query string parameters)
- POST – sending form data (FormData object)
- Content-Type header is very important
- Loading state makes UX better
- Error handling is mandatory (status codes + network errors)
- PHP side → always set correct header and validate input
Next step you may want:
- AJAX with JSON (modern standard)
- Live search / autocomplete with AJAX + PHP
- File upload with progress bar
- Loading spinner + disable button during request
- Validation before sending (client + server)
Tell me what you want to learn/practice next! 😊
