Асинхронное взаимодействие с сервером через PHP и JavaScript

Раздел: Разработка на PHP

Основные подходы к AJAX взаимодействию с PHP

Эффективное решение: Fetch API с PHP в формате JSON

Современный способ асинхронного обмена данными с сервером использует встроенное API браузера fetch(). Серверный скрипт на PHP должен возвращать данные в JSON. Этот подход не требует внешних библиотек, поддерживает промисы и асинхронные функции.

Как отправить GET запрос и обработать JSON ответ?

Клиентский код (JavaScript):

fetch('api.php?action=get_users')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Ошибка:', error));

Серверный код (PHP) в файле api.php:

<?php
header('Content-Type: application/json; charset=utf-8');
$users = [
  ['id' => 1, 'name' => 'Иван'],
  ['id' => 2, 'name' => 'Мария']
];
echo json_encode($users);

Возможные проблемы:

  • Ошибки CORS при запросах с другого домена. Решение: настройка заголовка Access-Control-Allow-Origin на сервере.
  • Кеширование GET запросов. Решение: добавить уникальный параметр (?_=timestamp) или использовать POST.
  • Неверный Content-Type на сервере. Решение: установить header('Content-Type: application/json') до вывода данных.

Вариант 1: Как отправить POST данные с использованием FormData?

Для отправки форм без перезагрузки удобно использовать объект FormData. Он автоматически кодирует все поля формы.

const form = document.getElementById('myForm');
form.addEventListener('submit', function(e) {
  e.preventDefault();
  const fd = new FormData(form);
  fetch('submit.php', {
    method: 'POST',
    body: fd
  })
  .then(r => r.json())
  .then(data => console.log(data));
});

На сервере в submit.php данные доступны через $_POST и $_FILES.

<?php
header('Content-Type: application/json');
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
echo json_encode(['success' => true, 'name' => $name]);

Проблема: файлы могут не отправляться, если у формы отсутствует атрибут enctype="multipart/form-data". Решение: добавить этот атрибут в HTML или установить вручную через form.enctype = 'multipart/form-data'.

Вариант 2: Как отправить данные в формате JSON с клиента?

Иногда необходимо передать сложную структуру данных. Для этого используется JSON.stringify().

const data = {login: 'admin', password: '123'};
fetch('auth.php', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify(data)
})
.then(r => r.json())
.then(res => console.log(res));

На PHP для чтения JSON тела запроса используется file_get_contents('php://input').

<?php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
$login = $input['login'] ?? '';
echo json_encode(['status' => 'ok', 'login' => $login]);

Ошибка: пустой $_POST при отправке JSON. Решение: использовать php://input вместо суперглобальных массивов.

Вариант 3: Как использовать классический XMLHttpRequest?

Если требуется поддержка очень старых браузеров, применяется XMLHttpRequest.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'data.php?type=products', true);
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    var json = JSON.parse(xhr.responseText);
    console.log(json);
  }
};
xhr.send();

Проблема: обработка ошибок сети и таймаутов. Решение: проверять xhr.status и добавлять обработчики xhr.onerror.

Вариант 4: Как использовать jQuery.ajax для упрощения кода?

В проектах, где уже используется jQuery, можно воспользоваться его функциями.

$.ajax({
  url: 'api.php',
  method: 'POST',
  data: {name: 'John'},
  dataType: 'json',
  success: function(response) {
    console.log(response);
  },
  error: function(xhr, status, error) {
    console.error(error);
  }
});

Проблема: библиотека jQuery может быть избыточной для одного запроса. Решение: использовать нативный fetch, если нет других зависимостей.

Расширенные примеры использования AJAX с PHP

Пример 1: POST запрос с передачей JSON и обработка ошибок

Пример
<!-- index.html -->
<button id="sendBtn">Отправить данные</button>
<script>
document.getElementById('sendBtn').addEventListener('click', async () => {
  const payload = {
    userId: 123,
    email: 'user@example.com'
  };
  try {
    const response = await fetch('process.php', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify(payload)
    });
    if (!response.ok) throw new Error('Сервер вернул ошибку ' + response.status);
    const result = await response.json();
    console.log('Успех:', result);
  } catch (err) {
    console.error('Ошибка запроса:', err);
  }
});
</script>

<!-- process.php -->
<?php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || empty($input['email'])) {
  http_response_code(400);
  echo json_encode(['error' => 'Некорректные данные']);
  exit;
}
// имитация сохранения
$response = ['id' => $input['userId'], 'status' => 'saved'];
echo json_encode($response);
При успешной отправке в консоль выводится:
{id: 123, status: "saved"}
При ошибке (неверный email) выводится:
{error: "Некорректные данные"}

Пример 2: Загрузка файла с прогрессом (используя XMLHttpRequest)

Пример
<input type="file" id="fileInput" />
<progress id="progressBar" value="0" max="100"></progress>
<script>
document.getElementById('fileInput').addEventListener('change', function() {
  const file = this.files[0];
  const formData = new FormData();
  formData.append('file', file);

  const xhr = new XMLHttpRequest();
  xhr.open('POST', 'upload.php', true);

  xhr.upload.onprogress = function(e) {
    if (e.lengthComputable) {
      const percent = Math.round((e.loaded / e.total) * 100);
      document.getElementById('progressBar').value = percent;
    }
  };

  xhr.onload = function() {
    if (xhr.status === 200) {
      console.log('Файл загружен:', xhr.responseText);
    } else {
      console.error('Ошибка загрузки');
    }
  };

  xhr.send(formData);
});
</script>

<!-- upload.php -->
<?php
header('Content-Type: application/json');
if (empty($_FILES['file'])) {
  http_response_code(400);
  echo json_encode(['error' => 'Файл не получен']);
  exit;
}
$uploadDir = 'uploads/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0777, true);
$path = $uploadDir . basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], $path);
echo json_encode(['path' => $path, 'size' => $_FILES['file']['size']]);
Прогресс заполняется, после завершения выводится:
{"path":"uploads/photo.jpg","size":204800}

Пример 3: Отправка данных формы с валидацией на PHP и ответом в JSON

Пример
<form id="regForm">
  <input name="username" placeholder="Имя пользователя" />
  <input name="email" type="email" placeholder="Email" />
  <button type="submit">Зарегистрироваться</button>
</form>
<div id="message"></div>
<script>
document.getElementById('regForm').addEventListener('submit', async function(e) {
  e.preventDefault();
  const formData = new FormData(this);
  try {
    const response = await fetch('register.php', { method: 'POST', body: formData });
    const result = await response.json();
    if (result.success) {
      document.getElementById('message').innerHTML = 'Регистрация прошла успешно!';
    } else {
      document.getElementById('message').innerHTML = 'Ошибка: ' + result.error;
    }
  } catch (err) {
    document.getElementById('message').innerHTML = 'Сетевая ошибка';
  }
});
</script>

<!-- register.php -->
<?php
header('Content-Type: application/json');
$errors = [];
if (empty($_POST['username'])) $errors[] = 'Не указано имя';
if (empty($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) $errors[] = 'Некорректный email';
if (!empty($errors)) {
  http_response_code(422);
  echo json_encode(['success' => false, 'error' => implode(', ', $errors)]);
  exit;
}
// регистрация...
echo json_encode(['success' => true, 'user' => $_POST['username']]);
При корректных данных выводится:
{"success":true,"user":"John"}
При ошибке валидации:
{"success":false,"error":"Не указано имя, Некорректный email"}

Пример 4: Использование async/await с fetch и обработка разных статусов ответа

Пример
async function getUsers() {
  const url = 'api.php?type=users';
  try {
    const response = await fetch(url);
    if (!response.ok) {
      if (response.status === 404) throw new Error('Ресурс не найден');
      if (response.status === 500) throw new Error('Ошибка сервера');
      throw new Error('Неизвестная ошибка');
    }
    const users = await response.json();
    console.log('Пользователи:', users);
  } catch (err) {
    console.error(err.message);
  }
}
getUsers();
При успехе:
Пользователи: [{id:1, name:"Иван"}, {id:2, name:"Мария"}]
При ошибке 404:
Ресурс не найден

AJAX с PHP - comments

En
Ajax php (php)