Обработка запросов и данных в PHP: варианты реализации

Раздел:

Основные подходы к обработке данных в PHP

Одним из наиболее эффективных решений для безопасной обработки входящих данных является использование встроенных функций фильтрации filter_input() и filter_var(). Они позволяют одновременно проверять тип данных, очищать от нежелательных символов и валидировать значения без написания лишнего кода.

Пример получения и проверки email через GET-параметр:

$email = filter_input(INPUT_GET, 'user_email', FILTER_VALIDATE_EMAIL);
if ($email === false) {
    // обработка ошибки
    die('Некорректный email');
}

Если требуется целое число из POST:

$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 120)));
if ($age === false) {
    // значение отсутствует или не проходит валидацию
}

Цель данного подхода – минимизировать риски XSS и SQL-инъекций на этапе получения данных, а также сократить объём кода.

Типичные ошибки: использование фильтра без проверки результата (filter_input возвращает null для отсутствующего ключа, false при невалидном значении).

Проблема: если не проверить isset() до фильтрации, можно получить false и принять его за пустое значение. Решение: сначала проверять существование ключа через isset() или использовать фильтр с флагом FILTER_NULL_ON_FAILURE.

Как получить данные из суперглобальных массивов без фильтрации?

Прямое обращение к $_GET, $_POST, $_SERVER допускается, но опасно. Данные могут содержать вредоносный код. Пример:

$name = $_POST['username'];

Такое использование оправдано только при немедленном экранировании перед выводом или записью в БД. Цель – быстрый доступ, если данные заведомо безопасны (например, внутренние параметры).

Главная проблема: нет автоматической защиты от XSS и SQL-инъекций. Ошибка: забыть обработать данные перед использованием. Решение: всегда применять htmlspecialchars() для вывода в HTML и подготовленные запросы для БД.

Как экранировать строки для SQL-запросов?

Функция mysqli_real_escape_string() экранирует спецсимволы для использования в составленном SQL-запросе.

$safe_name = mysqli_real_escape_string($connection, $_POST['name']);
$sql = "SELECT * FROM users WHERE name = '$safe_name'";

Цель – предотвратить вставку произвольного SQL-кода, но лучше использовать подготовленные запросы. Применяется в легаси-проектах.

Ошибка: забыть экранировать даже один параметр. Проблема: функция зависит от активного соединения с БД. Решение: переходить на PDO.

Как защититься от SQL-инъекций современным способом?

Подготовленные запросы в PDO отделяют код от данных. Пример с именованными плейсхолдерами:

$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $_POST['email']]);
$user = $stmt->fetch();

Цель – полная защита от инъекций, автоматическое экранирование PDO. Этот вариант считается наиболее эффективным для работы с базами данных.

Проблема: неправильное использование (например, эмуляция подготовленных запросов или отключение эмуляции) может снизить защиту. Решение: использовать PDO::ATTR_EMULATE_PREPARES в false и реальные подготовленные запросы.

Как обрабатывать данные с использованием filter_var для одиночных переменных?

Функция filter_var() принимает значение, а не суперглобальный массив. Подходит, когда данные уже извлечены:

$input = 'some@email.com';
$clean_email = filter_var($input, FILTER_SANITIZE_EMAIL);
$valid_email = filter_var($clean_email, FILTER_VALIDATE_EMAIL);

Цель – гибкая фильтрация и валидация любой строки. Используется для данных из файлов, API и т.д.

Ошибка: перепутать санитизацию и валидацию. Санитизация удаляет недопустимые символы, валидация проверяет формат. Решение: сначала санитизировать, потом валидировать.

Расширенные примеры обработки данных

Пример 1: Обработка формы регистрации с полной валидацией и вставкой в БД

Форма содержит поля: имя (строка), email, пароль, возраст (int). Используем filter_input для каждого поля, хешируем пароль через password_hash, вставляем через PDO.

Пример
<?
$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]);
$password = $_POST['password'] ?? '';

if (!$name || !$email || !$age || strlen($password) < 8) {
    die('Неверные данные');
}

$hash = password_hash($password, PASSWORD_DEFAULT);

$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->prepare('INSERT INTO users (name, email, age, password) VALUES (:n, :e, :a, :p)');
$stmt->execute(['n' => $name, 'e' => $email, 'a' => $age, 'p' => $hash]);
echo 'Пользователь добавлен';
?>
При успешной вставке: Пользователь добавлен
При ошибке валидации: Неверные данные

Пример 2: Загрузка файла с проверкой типа и размера

Проверяем расширение, MIME-тип и размер. Перемещаем загруженный файл в безопасную директорию.

Пример
<?
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$max_size = 2 * 1024 * 1024; // 2MB
$upload_dir = __DIR__ . '/uploads/';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $file = $_FILES['file'];
    
    if ($file['error'] !== UPLOAD_ERR_OK) {
        die('Ошибка загрузки');
    }
    
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    
    if (!in_array($mime, $allowed_types)) {
        die('Недопустимый тип файла');
    }
    
    if ($file['size'] > $max_size) {
        die('Файл слишком большой');
    }
    
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $new_name = uniqid() . '.' . $ext;
    
    if (move_uploaded_file($file['tmp_name'], $upload_dir . $new_name)) {
        echo 'Файл сохранён: ' . $new_name;
    } else {
        echo 'Ошибка перемещения';
    }
}
?>
При загрузке PNG 1.5 МБ: Файл сохранён: 65a1f8e2c3d45.png
При попытке загрузить скрипт: Недопустимый тип файла

Пример 3: Обработка JSON из тела запроса (API)

Получаем JSON через php://input, декодируем, валидируем каждое поле.

Пример
<?
$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    echo json_encode(['error' => 'Некорректный JSON']);
    exit;
}

$name = filter_var($data['name'] ?? '', FILTER_SANITIZE_STRING);
$email = filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL);

if (!$name || !$email) {
    http_response_code(422);
    echo json_encode(['error' => 'Отсутствуют обязательные поля или неверный формат']);
    exit;
}

echo json_encode(['status' => 'ok', 'name' => $name, 'email' => $email]);
?>
Запрос: {"name":"Иван", "email":"ivan@example.com"}
Ответ: {"status":"ok","name":"Иван","email":"ivan@example.com"}

Запрос: {"name":"Петр"}
Ответ: {"error":"Отсутствуют обязательные поля или неверный формат"}

Обработка данных в PHP - comments

En
обработка php (php)