PHP и AJAX
Узнайте, как использовать PHP AJAX для создания динамичных веб-приложений, обновляющих страницу без перезагрузки.
В этой главе объясняется, как совместить AJAX (в браузере) с PHP (на сервере), чтобы страница могла общаться с сервером в фоновом режиме и обновлять только изменившуюся часть — без полной перезагрузки. Вы создадите полный рабочий пример, увидите, как читать запрос в PHP и возвращать JSON, а также узнаете правила безопасности и обработки ошибок, которые необходимы в реальных приложениях.
Что такое PHP AJAX?
AJAX расшифровывается как Asynchronous JavaScript and XML. Несмотря на название, современный AJAX редко использует XML — он отправляет и получает JSON, поскольку JSON напрямую отображается на объекты JavaScript и массивы PHP. Ключевое слово — асинхронный: браузер отправляет запрос и продолжает работу. Когда сервер отвечает, колбэк обновляет страницу. Пользователь никогда не видит пустой перезагружающийся экран.
«PHP AJAX» — это просто данный паттерн, где PHP выступает на стороне сервера: JavaScript отправляет запрос, PHP-скрипт обрабатывает его (зачастую выполняя запрос к базе данных), и PHP возвращает JSON для отображения в JavaScript.
Распространённые применения:
- Живой поиск / автодополнение — подсказки появляются по мере ввода.
- Встроенная валидация формы — проверка имени пользователя или email до отправки.
- Кнопки «лайк» / голосование / «в избранное» — обновление счётчика без перехода со страницы.
- Бесконечная прокрутка и «загрузить ещё» — получение следующей страницы результатов по запросу.
Как работает AJAX-запрос
Каждый цикл запроса-ответа всегда проходит одни и те же четыре шага:
- Событие — пользователь вводит текст, нажимает или отправляет форму. JavaScript перехватывает событие.
- Запрос — JavaScript отправляет HTTP-запрос на PHP-эндпоинт (с помощью
fetchилиXMLHttpRequest). - Работа сервера — PHP читает входные данные из
$_GET,$_POSTили тела запроса, выполняет свою работу (например, запрос к базе данных) и возвращает JSON-ответ черезecho. - Обновление — JavaScript получает JSON, разбирает его и обновляет DOM.
Браузер является клиентом, а PHP-скрипт — сервером. Они обмениваются только небольшими порциями данных, вот почему AJAX воспринимается как мгновенный по сравнению с перезагрузкой целой страницы.
Отправка запроса: fetch и XMLHttpRequest
XMLHttpRequest (XHR) — это оригинальный AJAX API. fetch — современная, основанная на промисах замена: короче, проще для чтения и встроена во все современные браузеры. Используйте fetch для нового кода; XHR нужен только при поддержке очень старых браузеров.
// 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();Чтение запроса и ответ с JSON в PHP
То, как PHP читает входящие данные, зависит от того, как JavaScript их отправил:
| JavaScript отправляет | PHP читает через |
|---|---|
Строку запроса URL (?q=...) | $_GET['q'] |
FormData (настоящая форма) | $_POST['field'] |
Тело JSON.stringify(obj) | json_decode(file_get_contents('php://input'), true) |
Какими бы ни были входные данные, ответ должен быть JSON с правильным заголовком, чтобы браузер корректно его разобрал:
<?php
header('Content-Type: application/json');
echo json_encode(['status' => 'success', 'value' => 42]);Строка header() сообщает браузеру, что тело — это JSON. json_encode() преобразует массив PHP в строку JSON. Полную справку смотрите в PHP JSON и json_encode().
Полный пример: живые подсказки поиска
Это полное рабочее автодополнение: введите текст в поле, JavaScript выполнит запрос к search.php, и PHP вернёт совпадающие элементы в виде JSON.
HTML + JavaScript (страница):
<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]);Введите ap, и список покажет все фрукты, содержащие эти буквы — apple, apricot и grape — а страница никогда не перезагрузится. Чтобы получать подсказки из базы данных вместо массива в памяти, используйте подготовленный запрос, как показано в AJAX и база данных MySQL.
Всегда используйте подготовленные запросы. Никогда не вставляйте
$_GET['q']напрямую в строку SQL — это дыра для SQL-инъекции. Используйте связанные параметры (см. PHP MySQLi).
Встроенная валидация формы
Проверяйте поле на сервере до того, как пользователь отправит всю форму. Те же PHP-правила, которые защищают отправку, можно повторно использовать для AJAX-проверки.
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) собирает все поля, поэтому PHP читает их из $_POST. Более подробное описание форм смотрите в Валидация форм PHP и Суперглобальные переменные PHP $_GET / $_POST.
Распространённые подводные камни
- CORS. Запрос к другому источнику (домен, порт или схема) блокируется, если PHP-сервер не отправляет
Access-Control-Allow-Origin. Запросы к тому же источнику ничего не требуют. - Устанавливайте заголовок JSON. Отсутствие
header('Content-Type: application/json')всё равно работает сres.json(), но ломает инструменты, которые опираются на тип содержимого. Всегда устанавливайте его. - Обрабатывайте ошибки. Сбои сети и ответы 500 должны перехватываться — добавляйте
.catch()и проверяйтеres.ok, иначе интерфейс молча ничего не сделает. - Используйте дебаунс для живых запросов. Без дебаунса
setTimeout, как показано выше, каждое нажатие клавиши отправляет запрос и перегружает сервер. - Экранируйте вывод, который вставляете в DOM. Вставка необработанного серверного текста через
innerHTMLможет привести к XSS; экранируйте данные или используйтеtextContentдля ненадёжных данных.
Итог
PHP AJAX позволяет странице обмениваться небольшими объёмами данных с сервером в фоновом режиме и обновляться на месте. JavaScript отправляет запрос с помощью fetch, PHP читает его из $_GET/$_POST/php://input, выполняет свою работу и возвращает JSON через json_encode(). Используйте подготовленные запросы для входных данных, устанавливайте заголовок JSON и всегда обрабатывайте ошибки.
Следующие шаги: подключите AJAX к реальной базе данных в AJAX и MySQL и подробно изучите формат ответа в PHP JSON.