Принимаем данные в PHP: формы, файлы, JSON и внешние запросы
Общие принципы отправки данных в PHP
При разработке веб-приложений на PHP одной из ключевых задач является получение данных от клиента. Данные могут приходить различными способами: через HTML-формы, AJAX-запросы, загрузку файлов или напрямую через URL. Каждый метод имеет свои особенности, ограничения и случаи применения. В этой статье разбираются основные подходы к приёму данных в PHP, даются рабочие примеры и предупреждается о типичных ошибках.
Основной и наиболее эффективный способ: обработка POST-данных с валидацией
Для большинства веб-форм, где требуется передача конфиденциальной или объёмной информации, используется метод POST. Данные передаются в теле HTTP-запроса и не отображаются в URL. В PHP они становятся доступны через суперглобальный массив $_POST.
<?php
// Файл handler.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
$errors = [];
if (empty($name)) {
$errors[] = 'Поле имени обязательно';
}
if ($email === false) {
$errors[] = 'Некорректный email';
}
if (empty($errors)) {
// сохранение или отправка данных
$message = 'Данные приняты: ' . htmlspecialchars($name) . ', ' . htmlspecialchars($email);
} else {
$message = implode('<br>', $errors);
}
}
?>
<!DOCTYPE html>
<html>
<form method="post" action="">
Имя: <input type="text" name="name"><br>
Email: <input type="email" name="email"><br>
<button type="submit">Отправить</button>
</form>
</html>Пояснения: метод формы POST скрывает данные от прямого просмотра в адресной строке. Для безопасного вывода используется htmlspecialchars, чтобы предотвратить XSS-атаки. Валидация через filter_var проверяет корректность email до обработки.
Типичные проблемы и их решения:
- Проблема: Пустой массив $_POST при отправке формы. Решение: убедиться, что форма имеет атрибут
method="post"и поле name у каждого элемента. - Проблема: Специальные символы в выводе. Решение: применять
htmlspecialchars()или использовать подготовленные запросы для базы данных. - Проблема: Длинные строки или отсутствие ограничений. Решение: настроить директивы
post_max_sizeиmax_input_varsв php.ini.
Как передать данные через URL (GET-запросы)?
Метод GET используется для идемпотентных запросов, когда данные не меняют состояние сервера (например, поиск, фильтры). Данные передаются в строке запроса и видны в URL. В PHP доступны через $_GET.
<!-- Форма с method="get" -->
<form method="get" action="search.php">
<input type="text" name="q" placeholder="Поиск...">
<button type="submit">Искать</button>
</form>
<?php
// search.php
if (isset($_GET['q'])) {
$query = trim($_GET['q']);
// проверка на пустую строку
if ($query !== '') {
echo 'Вы ищете: ' . htmlspecialchars($query);
}
}
?>Важно: GET не подходит для паролей или больших объёмов данных (ограничение длины URL обычно 2048 символов). Также не стоит передавать чувствительную информацию – она остаётся в истории браузера и логах сервера.
Как загрузить файл на сервер в PHP?
Загрузка файлов выполняется через форму с enctype="multipart/form-data" и методом POST. Файлы доступны в массиве $_FILES.
<form method="post" enctype="multipart/form-data">
Выберите изображение:
<input type="file" name="avatar">
<button type="submit">Загрузить</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['avatar'])) {
$file = $_FILES['avatar'];
// проверка ошибок
if ($file['error'] === UPLOAD_ERR_OK) {
$allowed = ['image/jpeg', 'image/png'];
if (in_array($file['type'], $allowed) && $file['size'] < 2 * 1024 * 1024) {
$dest = 'uploads/' . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $dest)) {
echo 'Файл сохранён: ' . $dest;
}
} else {
echo 'Недопустимый тип или размер файла';
}
} else {
echo 'Ошибка загрузки: код ' . $file['error'];
}
}
?>Типичные ошибки: превышение лимита upload_max_filesize или post_max_size; отсутствие папки назначения; выполнение кода до проверки ошибок. Решение: всегда проверять $file['error'] и настраивать php.ini.
Как принимать JSON-данные (например, от REST API)?
Когда данные приходят в формате JSON (через Content-Type: application/json), PHP не заполняет $_POST. Нужно читать сырой поток php://input.
<?php
// Чтение JSON из тела запроса
$json = file_get_contents('php://input');
// Преобразование в массив
$data = json_decode($json, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($data)) {
$name = $data['name'] ?? 'Не указано';
echo 'Имя: ' . htmlspecialchars($name);
} else {
http_response_code(400);
echo 'Некорректный JSON';
}
?>
<!-- Пример отправки через fetch -->
<script>
fetch('/api.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Иван', age: 30})
});
</script>Проблема: часто забывают указать корректный заголовок Content-Type на клиенте – тогда php://input может быть пустым. Решение: на сервере проверять не только JSON, но и наличие данных.
Как обработать AJAX-запросы (XMLHttpRequest, fetch)?
Для динамических веб-приложений данные отправляются асинхронно. Серверная часть остаётся той же: в зависимости от Content-Type данные попадают в $_POST (для form-data) или в php://input (для JSON).
<?php
// ajax_handler.php
header('Content-Type: application/json');
$input = json_decode(file_get_contents('php://input'), true);
if ($input && isset($input['action'])) {
$response = ['status' => 'ok', 'message' => 'Действие: ' . $input['action']];
} else {
$response = ['status' => 'error', 'message' => 'Неверные данные'];
}
echo json_encode($response);
?>
<script>
fetch('ajax_handler.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({action: 'save'})
}).then(r => r.json()).then(console.log);
</script>Content-Type при использовании fetch – PHP не поймёт, как обработать данные. Решение: явно указывать Content-Type.Как отправить данные из PHP на внешний сервер (cURL)?
Иногда требуется передать данные на другой веб-сервер (например, платёжный шлюз). Для этого используется библиотека cURL.
<?php
$ch = curl_init('https://api.example.com/submit');
$payload = json_encode(['key' => 'value']);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
echo 'Ошибка cURL: ' . curl_error($ch);
} else {
echo 'HTTP код: ' . $httpCode . ', ответ: ' . $response;
}
curl_close($ch);
?>Цель: интеграция с внешними API. Проблемы: неверные SSL-сертификаты (решение: CURLOPT_SSL_VERIFYPEER = false для тестирования, но не для продакшена), таймауты, некорректные заголовки.
Расширенные примеры отправки данных в PHP
Пример 1. Форма регистрации с валидацией и сохранением в файл
<!DOCTYPE html>
<html>
<body>
<form method="post" enctype="multipart/form-data">
<label>Логин: <input type="text" name="login" required></label><br>
<label>Пароль: <input type="password" name="pass" required></label><br>
<label>Аватар: <input type="file" name="avatar" accept="image/*"></label><br>
<label>Подписка на рассылку: <input type="checkbox" name="subscribe" value="yes"></label><br>
<button type="submit">Зарегистрироваться</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$login = trim($_POST['login'] ?? '');
$pass = $_POST['pass'] ?? '';
$subscribe = isset($_POST['subscribe']) ? 'да' : 'нет';
$errors = [];
if (strlen($login) < 3) $errors[] = 'Логин должен содержать минимум 3 символа';
if (strlen($pass) < 6) $errors[] = 'Пароль должен быть не менее 6 символов';
$avatarPath = '';
if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$file = $_FILES['avatar'];
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$allowed = ['jpg', 'jpeg', 'png', 'gif'];
if (in_array(strtolower($ext), $allowed) && $file['size'] < 2*1024*1024) {
$avatarPath = 'uploads/avatar_' . uniqid() . '.' . $ext;
move_uploaded_file($file['tmp_name'], $avatarPath);
} else {
$errors[] = 'Недопустимый формат или размер аватара';
}
}
if (empty($errors)) {
$record = [
'login' => $login,
'pass_hash' => password_hash($pass, PASSWORD_DEFAULT),
'avatar' => $avatarPath,
'subscribe' => $subscribe,
'time' => date('Y-m-d H:i:s')
];
file_put_contents('users.json', json_encode($record, JSON_PRETTY_PRINT) . PHP_EOL, FILE_APPEND | LOCK_EX);
echo 'Регистрация успешна';
} else {
echo '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
}
}
?>
</body>
</html>Результат (при успехе): строка 'Регистрация успешна' и запись в файл users.json. При ошибке – список ошибок.
Пример 2. Приём нескольких одинаковых полей (массив) через POST
<!-- Форма с массивом -->
<form method="post">
<input type="text" name="phones[]" placeholder="Телефон 1"><br>
<input type="text" name="phones[]" placeholder="Телефон 2"><br>
<input type="text" name="phones[]" placeholder="Телефон 3"><br>
<button type="submit">Отправить</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['phones'])) {
$phones = array_map('trim', $_POST['phones']);
$phones = array_filter($phones); // удаляем пустые
echo 'Переданы номера: ' . implode(', ', array_map('htmlspecialchars', $phones));
}
?>Пример 3. Отправка данных методом GET с несколькими параметрами и экранированием URL
<?php
// Генерация ссылки с параметрами
$base = 'https://site.com/search.php?';
$params = [
'q' => 'php отправка',
'page' => 2,
'lang' => 'ru'
];
$url = $base . http_build_query($params);
echo 'Ссылка: <a href="' . htmlspecialchars($url) . '">перейти</a>';
// Результат: https://site.com/search.php?q=php+%D0%BE%D1%82%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B0&page=2&lang=ru
?>Пример 4. Загрузка нескольких файлов с именами в массиве
<form method="post" enctype="multipart/form-data">
<input type="file" name="images[]" multiple>
<button type="submit">Загрузить</button>
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_FILES['images'])) {
$files = $_FILES['images'];
$count = count($files['name']);
for ($i = 0; $i < $count; $i++) {
if ($files['error'][$i] === UPLOAD_ERR_OK) {
$dest = 'uploads/' . basename($files['name'][$i]);
move_uploaded_file($files['tmp_name'][$i], $dest);
echo 'Файл ' . $files['name'][$i] . ' загружен как ' . $dest . '<br>';
}
}
}
?>Пример 5. Отправка данных из PHP с помощью file_get_contents (stream context)
<?php
$data = ['username' => 'admin', 'password' => 'secret'];
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents('https://example.com/login', false, $context);
if ($result !== false) {
echo 'Ответ сервера: ' . $result;
} else {
echo 'Ошибка запроса';
}
?>Результат: тело ответа от удалённого сервера.
Пример 6. Обработка PUT/DELETE запросов (REST)
<?php
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'PUT') {
$data = json_decode(file_get_contents('php://input'), true);
echo 'PUT данные: ' . print_r($data, true);
} elseif ($method === 'DELETE') {
parse_str(file_get_contents('php://input'), $data);
echo 'DELETE: ' . $data['id'];
} else {
http_response_code(405);
}
?>Пример 7. Отправка формы с токеном CSRF
<?php
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die('CSRF атака!');
}
// дальнейшая обработка
echo 'Данные приняты';
}
?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<button type="submit">Отправить</button>
</form>При совпадении токена – 'Данные приняты'. При несовпадении – ошибка 'CSRF атака!'.