Обработка пользовательского ввода в PHP
Способы получения данных от пользователя
Использование filter_input для безопасного извлечения
Как получить значение из внешнего источника с автоматической проверкой типа?
Функция filter_input позволяет извлечь данные из суперглобальных массивов (INPUT_GET, INPUT_POST, INPUT_COOKIE и другие) с применением фильтра. Это наиболее надёжный способ, так как он объединяет получение и валидацию в одном вызове.
<?php
// Получение целого числа из GET параметра 'id'
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
// обработка ошибки
echo 'Некорректный id';
} else {
echo 'Получен id: ' . $id;
}
?>Php ввел (ввод данных в php)
При запросе page.php?id=42 выведет: Получен id: 42 При id=abc выведет: Некорректный id
Поддерживаются фильтры для целых чисел, строк с санитизацией, email, URL и других. При отсутствии параметра функция вернёт null, а при неверном типе - false.
Типичные ошибки: Путаница между false и null. Необходимо использовать строгое сравнение (===). Если параметр может быть равен 0, проверка через empty() приведёт к ложному срабатыванию.
<?php
$count = filter_input(INPUT_POST, 'count', FILTER_VALIDATE_INT);
if ($count === false) {
// неверный тип или ошибка
} elseif ($count === null) {
// параметр отсутствует
} // иначе $count содержит целое число (возможно 0)
?>
Случаи использования: Любые формы, где известен ожидаемый тип данных. Особенно полезен при работе с числовыми идентификаторами, датами, email адресами.
Прямой доступ к $_GET и $_POST
Как получить данные из строки запроса или тела POST запроса без дополнительной обработки?
Самый простой способ - обратиться к суперглобальным массивам напрямую. Однако такой подход требует ручной проверки существования индекса и валидации.
<?php
$name = isset($_POST['username']) ? $_POST['username'] : '';
$email = $_GET['email'] ?? ''; // оператор объединения с null
?>
После получения данных их нужно очищать перед выводом или использованием в запросах.
Проблемы: Отсутствие проверки может привести к ошибкам уровня E_NOTICE. Данные не проходят фильтрацию, что создаёт риск XSS и SQL инъекций. Применяется только для отладочных целей или в строго контролируемой среде.
Использование $_REQUEST для объединённого доступа
Как получить данные независимо от метода запроса (GET или POST)?
Массив $_REQUEST содержит содержимое $_GET, $_POST и $_COOKIE. Удобен для простых скриптов, когда метод не важен. Однако его использование не рекомендуется из-за потенциальной путаницы и меньшей безопасности.
<?php
$action = $_REQUEST['action'] ?? 'default';
?>
Недостатки: Нельзя контролировать приоритет источника. Если один и тот же параметр передан и GET, и POST, поведение зависит от конфигурации (переменная variables_order). Это может привести к неожиданным результатам. Лучше явно указывать источник.
Очистка строк с помощью strip_tags и htmlspecialchars
Как удалить HTML теги и экранировать специальные символы для безопасного вывода?
Функция strip_tags удаляет все HTML и PHP теги из строки. htmlspecialchars преобразует специальные символы в HTML сущности, предотвращая внедрение скриптов.
<?php
$raw = $_POST['message'] ?? '';
$clean = strip_tags($raw);
$safe = htmlspecialchars($clean, ENT_QUOTES, 'UTF-8');
echo $safe;
?>
Ошибки: strip_tags не защищает от всех XSS атак, если в строке остаются разрешённые теги. htmlspecialchars следует применять только при выводе, а не при сохранении в БД (иначе данные будут закодированы дважды).
Валидация с помощью регулярных выражений
Как проверить, соответствует ли входная строка определённому шаблону (например, номер телефона)?
Функция preg_match позволяет задать шаблон и проверить строку на соответствие. Это подходит для сложных форматов.
<?php
$phone = $_POST['phone'] ?? '';
if (preg_match('/^\+?[1-9]\d{1,14}$/', $phone)) {
echo 'Номер корректен';
} else {
echo 'Неверный формат номера';
}
?>
Проблемы: Регулярные выражения могут быть медленными при большом объёме данных. Их сложно поддерживать. Рекомендуется использовать встроенные фильтры PHP, если они подходят для задачи.
Подробные примеры обработки ввода
Фильтрация массива параметров с помощью filter_input_array
Функция filter_input_array позволяет обработать сразу несколько полей, задав массив правил.
<?php
$filters = [
'name' => FILTER_SANITIZE_STRING,
'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 120]],
'email' => FILTER_VALIDATE_EMAIL
];
$result = filter_input_array(INPUT_POST, $filters);
var_dump($result);
?>
Пример вывода при POST name=John&age=25&email=john@test.com:
array(3) {
["name"]=> string(4) "John"
["age"]=> int(25)
["email"]=> string(14) "john@test.com"
}
Если age=abc, то age станет false.
Обработка ввода из командной строки (CLI)
В скриптах для консоли данные можно читать через fgets из STDIN или использовать аргументы командной строки ($argv).
<?php
echo "Введите ваше имя: ";
$handle = fopen("php://stdin", "r");
$name = trim(fgets($handle));
fclose($handle);
echo "Привет, $name!\n";
// Использование аргументов:
// php script.php --name=John
$longopts = [
"name:", // обязательное значение
];
$options = getopt("", $longopts);
if (isset($options['name'])) {
echo "Аргумент name: " . $options['name'] . "\n";
}
?>
При запуске php input.php и вводе Alice: Привет, Alice! При запуске php input.php --name=Bob: Аргумент name: Bob
Работа с загрузкой файлов через $_FILES
Файлы передаются через форму с enctype="multipart/form-data". Проверка типа и размера обязательна.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['avatar'])) {
$file = $_FILES['avatar'];
$allowedTypes = ['image/jpeg', 'image/png'];
if (in_array($file['type'], $allowedTypes) && $file['size'] < 2*1024*1024) {
$dest = 'uploads/' . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $dest)) {
echo 'Файл загружен: ' . $dest;
} else {
echo 'Ошибка перемещения файла';
}
} else {
echo 'Недопустимый тип или размер файла';
}
}
?>
При успешной загрузке: Файл загружен: uploads/photo.jpg
Безопасная работа с JSON вводом
Современные API часто передают данные в JSON. Чтение потока php://input и декодирование.
<?php
$json = file_get_contents('php://input');
$data = json_decode($json, true); // ассоциативный массив
if (json_last_error() === JSON_ERROR_NONE) {
$name = $data['name'] ?? '';
echo 'Имя: ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
} else {
echo 'Неверный JSON';
}
?>
При POST с телом {"name":"Анна"} выведет: Имя: Анна
Пример фильтрации с пользовательской функцией обратного вызова
Можно использовать FILTER_CALLBACK для собственной валидации.
<?php
function validate_username($value) {
// только буквы и цифры, длина 3-20
if (preg_match('/^[a-zA-Z0-9]{3,20}$/', $value)) {
return $value;
}
return false;
}
$username = filter_input(INPUT_POST, 'username', FILTER_CALLBACK, ['options' => 'validate_username']);
if ($username) {
echo 'Имя пользователя: ' . $username;
} else {
echo 'Некорректное имя';
}
?>
При POST username=JohnDoe выведет: Имя пользователя: JohnDoe При username=Jo (слишком короткое) выведет: Некорректное имя