AJAX запросы на PHP: от простого к сложному
Основы AJAX запросов к PHP
Современный способ: Fetch API + JSON
Для клиент-серверного взаимодействия часто используется Fetch API. Он позволяет отправлять асинхронные запросы и обрабатывать ответы в формате JSON.
// Клиентская часть (JavaScript)
fetch('server.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Иван', age: 30 })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));
Ajax запросы php (ajax запросы на php)
На стороне PHP получаем данные и возвращаем JSON:
// server.php
$input = json_decode(file_get_contents('php://input'), true);
$name = $input['name'] ?? '';
$age = $input['age'] ?? 0;
$response = ['status' => 'ok', 'message' => 'Привет, ' . $name];
header('Content-Type: application/json');
echo json_encode($response);
Типичные проблемы:
- Забыли установить заголовок
Content-Type: application/json– сервер не сможет прочитать тело запроса. - Ошибки CORS, если клиент и сервер на разных доменах – требуется добавить заголовки
Access-Control-Allow-Origin. - Некорректный JSON в ответе – проверяйте
json_last_error().
Как реализовать AJAX-запрос через XMLHttpRequest?
Классический способ, подходит для старых браузеров.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'server.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
if (xhr.status === 200) {
console.log(xhr.responseText);
}
};
xhr.send('name=Иван&age=30');
На PHP данные придут как обычные $_POST переменные:
$name = $_POST['name'] ?? '';
echo json_encode(['message' => 'Привет, ' . $name]);
Проблемы:
- Не забывайте про кодировку URL при отправке данных.
- Сложнее обрабатывать ошибки, чем в Fetch.
Как отправить AJAX-запрос с помощью jQuery?
jQuery упрощает синтаксис и автоматически обрабатывает JSON.
$.ajax({
url: 'server.php',
method: 'POST',
data: { name: 'Иван', age: 30 },
dataType: 'json'
})
.done(function(response) {
console.log(response);
})
.fail(function(jqXHR, textStatus) {
console.error('Ошибка:', textStatus);
});
На PHP ничего не меняется.
Как передать файл через AJAX на PHP?
Используем FormData с Fetch или jQuery.
const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('description', 'Мой файл');
fetch('upload.php', {
method: 'POST',
body: form
})
.then(res => res.json())
.then(data => console.log(data));
В PHP:
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
$uploadDir = 'uploads/';
$filename = basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], $uploadDir . $filename);
echo json_encode(['status' => 'ok']);
} else {
http_response_code(400);
echo json_encode(['error' => 'Ошибка загрузки']);
}
Проблемы:
- Не устанавливайте заголовок Content-Type вручную – браузер сам задаст multipart/form-data.
- Проверяйте размер файла и разрешённые типы.
Как обработать разные HTTP методы (GET, PUT, DELETE)?
Fetch и jQuery позволяют указать метод. На PHP обращайтесь к соответствующему массиву ($_GET, php://input для PUT).
// GET запрос
fetch('server.php?id=5')
.then(res => res.json())
.then(data => console.log(data));
// server.php для GET
$id = $_GET['id'] ?? 0;
// ...
// PUT запрос
fetch('server.php', {
method: 'PUT',
body: JSON.stringify({id: 5, name: 'Новое имя'})
});
// server.php для PUT
$input = json_decode(file_get_contents('php://input'), true);
// ...
Расширенные примеры AJAX-запросов на PHP
Допустим, есть форма регистрации. Отправляем данные через AJAX, сервер проверяет и возвращает ошибки.
// client.js
const form = document.getElementById('regForm');
form.addEventListener('submit', e => {
e.preventDefault();
const data = new FormData(form);
fetch('register.php', {
method: 'POST',
body: data
})
.then(response => response.json())
.then(result => {
if (result.success) {
alert('Регистрация успешна');
} else {
// Вывести ошибки
Object.keys(result.errors).forEach(key => {
console.log(key + ': ' + result.errors[key]);
});
}
});
});
// register.php
$response = ['success' => false, 'errors' => []];
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
if (empty($name)) {
$response['errors']['name'] = 'Имя обязательно';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response['errors']['email'] = 'Некорректный email';
}
if (empty($response['errors'])) {
// сохраняем в БД...
$response['success'] = true;
}
header('Content-Type: application/json');
echo json_encode($response);
Результат (если ошибки):
{ "success": false, "errors": {"name": "Имя обязательно"} }
Загружаем следующий блок контента при прокрутке страницы.
// client.js
let page = 1;
const container = document.getElementById('content');
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 200) {
page++;
fetch('load-more.php?page=' + page)
.then(res => res.json())
.then(data => {
data.items.forEach(item => {
const div = document.createElement('div');
div.textContent = item.title;
container.appendChild(div);
});
});
}
});
// load-more.php
$page = intval($_GET['page'] ?? 1);
$limit = 10;
$offset = ($page - 1) * $limit;
// Выборка из БД
$items = [];
for ($i = $offset; $i < $offset + $limit; $i++) {
$items[] = ['title' => 'Элемент ' . $i, 'id' => $i];
}
header('Content-Type: application/json');
echo json_encode(['items' => $items, 'page' => $page]);
{"items":[{"title":"Элемент 10","id":10},...],"page":2}
Часто требуется передавать токен в заголовке Authorization.
// client.js
const token = 'some-jwt-token';
fetch('api/profile.php', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token,
'Accept': 'application/json'
}
})
.then(res => {
if (res.status === 401) throw new Error('Не авторизован');
return res.json();
})
.then(data => console.log(data));
// api/profile.php
$headers = getallheaders();
$auth = $headers['Authorization'] ?? '';
$token = str_replace('Bearer ', '', $auth);
// проверка токена...
if (!validToken($token)) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
// ...
Современный стиль с try/catch.
// client.js
async function createUser(userData) {
try {
const response = await fetch('api/users.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Ошибка сервера');
}
const data = await response.json();
console.log('Пользователь создан:', data);
} catch (error) {
console.error('Ошибка:', error.message);
}
}
createUser({ username: 'test', password: 'qwerty' });
// api/users.php
$input = json_decode(file_get_contents('php://input'), true);
if (empty($input['username']) || empty($input['password'])) {
http_response_code(400);
echo json_encode(['message' => 'Не хватает данных']);
exit;
}
// ...
Полезно для загрузки независимых данных.
const urls = ['user.php', 'posts.php', 'comments.php'];
const promises = urls.map(url => fetch(url).then(res => res.json()));
Promise.all(promises)
.then(([user, posts, comments]) => {
console.log('Пользователь:', user);
console.log('Посты:', posts);
console.log('Комментарии:', comments);
})
.catch(error => console.error('Ошибка:', error));