Обработка ввода в PHP: создание собственного класса и альтернативные методы

Раздел: Веб-разработка -> Обработка ввода

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

Наиболее эффективное решение: универсальный класс Input

Данный класс инкапсулирует получение данных из различных суперглобальных массивов ($_GET, $_POST, $_REQUEST), применяет фильтрацию, валидацию и преобразование типов. Основные возможности:

  • Единый интерфейс для доступа к данным запроса.
  • Автоматическая фильтрация с помощью встроенных фильтров PHP (FILTER_SANITIZE_STRING, FILTER_VALIDATE_INT и др.).
  • Поддержка значений по умолчанию.
  • Удобная работа с вложенными массивами (например, $_POST['user']['name']).

class Input {
    private $source;
    
    public function __construct($source = null) {
        $this->source = $source ?? $_REQUEST;
    }
    
    public function get($key, $default = null, $filter = FILTER_DEFAULT) {
        if (strpos($key, '.') !== false) {
            $keys = explode('.', $key);
            $value = $this->source;
            foreach ($keys as $k) {
                if (!isset($value[$k])) {
                    return $default;
                }
                $value = $value[$k];
            }
            return filter_var($value, $filter) ?: $default;
        }
        return isset($this->source[$key]) ? filter_var($this->source[$key], $filter) : $default;
    }
    
    public function has($key) {
        if (strpos($key, '.') !== false) {
            $keys = explode('.', $key);
            $value = $this->source;
            foreach ($keys as $k) {
                if (!isset($value[$k])) {
                    return false;
                }
                $value = $value[$k];
            }
            return true;
        }
        return isset($this->source[$key]);
    }
    
    public function all() {
        return $this->source;
    }
    
    public function only(array $keys) {
        $result = [];
        foreach ($keys as $key) {
            $result[$key] = $this->get($key);
        }
        return $result;
    }
}

Input class php (класс для обработки ввода в php)

Пример использования:


$input = new Input();
$name = $input->get('name', 'Гость', FILTER_SANITIZE_STRING);
$age = $input->get('age', 0, FILTER_VALIDATE_INT);
if ($input->has('user.email')) {
    $email = $input->get('user.email', null, FILTER_VALIDATE_EMAIL);
}

Типичные проблемы и решения:

  • Проблема: небезопасное использование $_REQUEST (может содержать куки). Решение: передавать конкретный источник ($_POST, $_GET) в конструктор.
  • Проблема: фильтр FILTER_DEFAULT не удаляет теги. Решение: использовать FILTER_SANITIZE_STRING или htmlspecialchars после получения.
  • Проблема: работа с массивами может вернуть неверный тип после фильтра. Решение: проверять тип результата и приводить к нужному.

Как обработать ввод без создания собственного класса: функция filter_input?

В PHP есть встроенные функции filter_input() и filter_var(), которые позволяют получать и фильтровать данные напрямую.


$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);
$age = filter_input(INPUT_GET, 'age', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]);

Цель: быстрая обработка единичных полей без создания классов. Подходит для простых скриптов.

Проблема: filter_input не поддерживает точечную нотацию для вложенных массивов. Для массивов (например, $_POST['user']) нужно использовать filter_var после ручного извлечения.

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

Прямой доступ к $_GET, $_POST, $_SERVER без дополнительных абстракций. Пример:


if (isset($_POST['email'])) {
    $email = trim($_POST['email']);
    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
        // валидный email
    }
}

Цель: полный контроль над обработкой, отсутствие накладных расходов. Подходит для небольших проектов.

Проблема: дублирование кода, риск забыть фильтрацию, сложность поддержки при росте проекта. Типичная ошибка: использование $_REQUEST без проверки источника (может привести к подмене данных).

Как использовать готовые библиотеки для обработки ввода (например, Symfony HttpFoundation)?

Компонент symfony/http-foundation предоставляет объекты Request и ParameterBag для работы с входными данными.


use Symfony\Component\HttpFoundation\Request;

$request = Request::createFromGlobals();
$name = $request->request->get('name', 'default');
$age = $request->query->getInt('age', 0);

Цель: использование проверенного решения с расширенной функциональностью (загрузка файлов, сессии, куки). Подходит для фреймворков и крупных проектов.

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

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

Пример 1: обработка файлов через класс Input

Добавим в класс метод file() для работы с $_FILES.

Пример

class Input {
    // ... остальные методы
    
    public function file($key) {
        if (isset($_FILES[$key]) && $_FILES[$key]['error'] === UPLOAD_ERR_OK) {
            return $_FILES[$key];
        }
        return null;
    }
}

$input = new Input();
$uploadedFile = $input->file('avatar');
if ($uploadedFile) {
    $name = $uploadedFile['name'];
    $tmpPath = $uploadedFile['tmp_name'];
    move_uploaded_file($tmpPath, 'uploads/' . basename($name));
}
// Результат: файл перемещен в папку uploads (если загрузка прошла успешно).
// В случае ошибки возвращается null.

Пример 2: цепочечная фильтрация и валидация

Добавим методы для последовательной обработки: сначала санитизация, потом валидация.

Пример

class Input {
    // ...
    public function sanitize($key, $filter = FILTER_SANITIZE_STRING) {
        $value = $this->get($key, null, $filter);
        return $value;
    }
    
    public function validate($key, $filter, $options = []) {
        $value = $this->get($key);
        if ($value === null) return false;
        return filter_var($value, $filter, ['options' => $options]) !== false;
    }
}

$input = new Input($_POST);
$email = $input->sanitize('email', FILTER_SANITIZE_EMAIL);
if ($input->validate('email', FILTER_VALIDATE_EMAIL)) {
    echo "Email корректен: $email";
} else {
    echo "Некорректный email";
}
// Ввод: <script>alert('xss')</script>user@example.com
// После санитизации: user@example.com (теги удалены)
// Валидация проходит, вывод: Email корректен: user@example.com

Пример 3: извлечение вложенных данных из JSON запроса

Для REST API данные часто приходят в формате JSON. Адаптируем класс для работы с php://input.

Пример

class JsonInput extends Input {
    public function __construct() {
        $raw = file_get_contents('php://input');
        $data = json_decode($raw, true) ?? [];
        parent::__construct($data);
    }
}

$input = new JsonInput();
$userId = $input->get('user.id', 0, FILTER_VALIDATE_INT);
$action = $input->get('meta.action', 'view');
// Тело запроса: {"user":{"id":42},"meta":{"action":"delete"}}
// Результат: $userId = 42, $action = "delete"

Пример 4: использование кастомных фильтров с callback

Создадим метод, применяющий произвольную функцию фильтрации.

Пример

class Input {
    // ...
    public function custom($key, callable $callback, $default = null) {
        $value = $this->get($key);
        return $value !== null ? $callback($value) : $default;
    }
}

$input = new Input($_POST);
$trimmed = $input->custom('name', function($v) {
    return trim(strip_tags($v));
});
// или с использованием стрелочной функции (PHP 7.4+)
$trimmed = $input->custom('name', fn($v) => trim(strip_tags($v)));
// Ввод: "  <b>Привет</b>  "
// Результат: "Привет" (пробелы и теги удалены)

Пример 5: получение всех данных с автоматической фильтрацией

Метод allFiltered() применяет фильтр ко всем элементам массива.

Пример

class Input {
    // ...
    public function allFiltered($filter = FILTER_SANITIZE_STRING) {
        return filter_var_array($this->source, $filter);
    }
}

$input = new Input($_GET);
$safeParams = $input->allFiltered(FILTER_SANITIZE_ENCODED);
print_r($safeParams);
// Входной массив: ['name' => '', 'id' => '123']
// Результат: Array ( [name] => %3Ctest%3E [id] => 123 )

Класс для обработки ввода в PHP - comments

En
Input class php (php)