Ввод данных в PHP: методы и практические примеры
Основной способ обработки ввода данных в PHP
Наиболее эффективный подход для работы с данными, переданными через формы или URL, заключается в использовании суперглобальных массивов в сочетании с фильтрацией и валидацией через функции filter_input или filter_var. Такой метод гарантирует безопасность и предсказуемость данных перед их использованием. Основной поток: клиент отправляет форму методом POST (или GET), сервер получает данные через $_POST или $_GET.
// Пример обработки POST запроса с проверкой
$inputData = [
'name' => filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING),
'age' => filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]),
'email' => filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL)
];
if ($inputData['age'] === false || $inputData['email'] === false) {
// Ошибка валидации
}
Этот способ позволяет сразу очистить и проверить данные, избегая ручного вызова trim() или htmlspecialchars(). Используется для большинства веб-форм: регистрация, обратная связь, поисковые запросы.
Типичные проблемы и их решения:
- Проблема: данные не проходят валидацию из‑за неожиданного формата. Решение: перед фильтрацией убедиться, что запрос содержит ожидаемые поля, проверять через isset() или $_SERVER['REQUEST_METHOD'].
- Проблема: XSS‑атаки через отображение неочищенных данных. Решение: при выводе использовать htmlspecialchars($value, ENT_QUOTES), а при вводе - фильтр FILTER_SANITIZE_STRING.
- Проблема: пустые поля считаются валидными. Решение: дополнительно проверять длину строки или значение через strlen() или empty() после фильтрации.
Как получить данные через GET запрос и использовать их для фильтрации?
GET применяется для передачи данных строкой запроса, например, в поиске или пагинации. Данные доступны через $_GET. Фильтрация обязательна, так как пользователь может изменить URL.
$search = filter_input(INPUT_GET, 'q', FILTER_SANITIZE_STRING);
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, ['options' => ['default' => 1]]);
Распространённые ошибки:
- Ошибка: не проверяется наличие параметра в URL. Решение: использовать isset($_GET['name']) или аргумент 'default' в фильтре.
- Ошибка: SQL‑инъекция при подстановке GET‑параметров в запрос. Решение: всегда использовать подготовленные выражения (PDO) или экранирование через mysqli_real_escape_string().
Как обрабатывать ввод данных из формы с несколькими одинаковыми полями (массивы)?
В HTML имена полей с квадратными скобками (например, items[]) создают массив в $_POST. Обработка требует преобразования каждого элемента.
// Форма: <input type="text" name="fruits[]" /> (несколько раз)
$fruits = isset($_POST['fruits']) ? $_POST['fruits'] : [];
$cleanFruits = [];
foreach ($fruits as $fruit) {
$cleanFruits[] = filter_var($fruit, FILTER_SANITIZE_STRING);
}
Типичные сложности:
- Проблема: неожиданные ключи или не числовые индексы. Решение: использовать array_values() для переиндексации или проверять тип ключа.
- Проблема: пустые строки в массиве. Решение: фильтровать через array_filter() с колбэком проверки strlen.
Как принимать данные в формате JSON (для REST API или AJAX)?
Когда клиент отправляет JSON (Content-Type application/json), данные не попадают в $_POST. Их читают из потока php://input.
$rawJson = file_get_contents('php://input');
$decoded = json_decode($rawJson, true);
if (json_last_error() !== JSON_ERROR_NONE) {
// Ошибка парсинга
}
$name = isset($decoded['name']) ? filter_var($decoded['name'], FILTER_SANITIZE_STRING) : null;
Возможные проблемы:
- Проблема: некорректный JSON. Решение: проверять json_last_error().
- Проблема: большие объёмы данных. Решение: лимитировать размер через $_SERVER['CONTENT_LENGTH'].
Как обработать загрузку файлов и текстовые поля одновременно?
Файлы попадают в $_FILES. После проверки ошибок (UPLOAD_ERR_OK) их перемещают в постоянное хранилище. Текстовые поля обрабатываются как обычно.
$description = filter_input(INPUT_POST, 'desc', FILTER_SANITIZE_STRING);
if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
$tmpName = $_FILES['avatar']['tmp_name'];
move_uploaded_file($tmpName, 'uploads/' . basename($_FILES['avatar']['name']));
}
Ошибки при работе с файлами:
- Ошибка: превышение размера файла. Решение: проверять $_FILES['field']['size'] и настройки upload_max_filesize в php.ini.
- Ошибка: неверный MIME‑тип. Решение: использовать finfo_file() для проверки.
- Ошибка: загрузка на сервер без расширения. Решение: генерировать уникальное имя и сохранять только разрешённые расширения.
Расширенные примеры обработки ввода данных
Пример 1: Комплексная валидация формы регистрации
Форма включает поля: имя (строка от 2 до 100 символов), email (валидный адрес), пароль (минимум 8 символов, хотя бы одна цифра), согласие (чекбокс). Используется комбинация filter_input и кастомных проверок.
// Обработчик формы (method=POST)
$errors = [];
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
if (strlen($name) < 2 || strlen($name) > 100) {
$errors[] = 'Имя должно содержать от 2 до 100 символов';
}
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($email === false) {
$errors[] = 'Укажите корректный email';
}
$password = filter_input(INPUT_POST, 'password', FILTER_UNSAFE_RAW);
if ($password === null || strlen($password) < 8 || !preg_match('/\d/', $password)) {
$errors[] = 'Пароль должен быть не короче 8 символов и содержать хотя бы одну цифру';
}
$agree = filter_input(INPUT_POST, 'agree', FILTER_VALIDATE_BOOLEAN);
if (!$agree) {
$errors[] = 'Необходимо согласие с условиями';
}
if (empty($errors)) {
// Сохранение в базу данных с подготовленным запросом
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// ...
} else {
// Вывод ошибок
}
Результат: при отправке пустых полей или невалидных данных формируется массив $errors.
Array
(
[0] => Имя должно содержать от 2 до 100 символов
[1] => Укажите корректный email
[2] => Пароль должен быть не короче 8 символов и содержать хотя бы одну цифру
[3] => Необходимо согласие с условиями
)
Пример 2: Обработка вложенных массивов из формы (например, товаров с количеством)
Форма содержит строки с полями product[id] и product[qty]. PHP автоматически создаёт многомерный массив.
// Форма:
// <input type="text" name="product[1][name]" value="Товар А" />
// <input type="number" name="product[1][qty]" value="2" />
// <input type="text" name="product[2][name]" value="Товар Б" />
// <input type="number" name="product[2][qty]" value="1" />
$products = isset($_POST['product']) ? $_POST['product'] : [];
$cleanProducts = [];
foreach ($products as $id => $item) {
$id = filter_var($id, FILTER_VALIDATE_INT);
if ($id === false) continue;
$name = filter_var($item['name'] ?? '', FILTER_SANITIZE_STRING);
$qty = filter_var($item['qty'] ?? 0, FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
if ($name === '' || $qty === 0) continue;
$cleanProducts[$id] = ['name' => $name, 'qty' => $qty];
}
print_r($cleanProducts);
Array
(
[1] => Array
(
[name] => Товар А
[qty] => 2
)
[2] => Array
(
[name] => Товар Б
[qty] => 1
)
)
Пример 3: Чтение и валидация JSON из PUT запроса (RESTful обновление)
Клиент отправляет JSON через PUT. Сервер считывает сырые данные и проверяет целостность.
// Предполагается, что Content-Type: application/json
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(400);
echo json_encode(['error' => 'Invalid JSON: ' . json_last_error_msg()]);
exit;
}
$id = filter_var($data['id'] ?? null, FILTER_VALIDATE_INT);
$title = filter_var($data['title'] ?? '', FILTER_SANITIZE_STRING);
$content = filter_var($data['content'] ?? '', FILTER_SANITIZE_STRING);
if (!$id || empty($title) || empty($content)) {
http_response_code(422);
echo json_encode(['error' => 'Missing required fields']);
exit;
}
// Обновление записи в БД
// ...
echo json_encode(['status' => 'updated']);
Результат (при успешном запросе):
{"status":"updated"}
Пример 4: Безопасная загрузка файла с генерацией имени
Загрузка изображения с проверкой типа, размера и созданием уникального имени.
$errors = [];
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
$maxSize = 2 * 1024 * 1024; // 2MB
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
if ($file['error'] !== UPLOAD_ERR_OK) {
$errors[] = 'Ошибка загрузки файла. Код: ' . $file['error'];
} else {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mimeType, $allowedTypes, true)) {
$errors[] = 'Разрешены только JPEG, PNG и GIF';
} elseif ($file['size'] > $maxSize) {
$errors[] = 'Файл превышает 2 MB';
} else {
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$newName = uniqid('img_', true) . '.' . $ext;
$destPath = __DIR__ . '/uploads/' . $newName;
if (move_uploaded_file($file['tmp_name'], $destPath)) {
echo 'Файл сохранён как ' . htmlspecialchars($newName);
} else {
$errors[] = 'Не удалось переместить файл';
}
}
}
}
if (!empty($errors)) {
foreach ($errors as $err) {
echo htmlspecialchars($err) . '<br>';
}
}
Результат (при успешной загрузке):
Файл сохранён как img_5f7c2a1b3e4d5.jpg