MidТеория4 min

Валидация входных данных

filter_input, filter_var, sanitization

filter_var — валидация и санитизация

<?php
declare(strict_types=1);

// VALIDATION — checks if value matches criteria (returns value or false)
$email = '[email protected]';
$valid = filter_var($email, FILTER_VALIDATE_EMAIL);
var_dump($valid);  // '[email protected]' (returns value if valid)

$invalid = filter_var('not-an-email', FILTER_VALIDATE_EMAIL);
var_dump($invalid);  // false

// Integer validation
$age = filter_var('25', FILTER_VALIDATE_INT);          // 25
$notInt = filter_var('25.5', FILTER_VALIDATE_INT);     // false
$zero = filter_var('0', FILTER_VALIDATE_INT);           // 0 (valid!)

// With options
$age = filter_var('25', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 150],
]);

// URL validation
$url = filter_var('https://example.com', FILTER_VALIDATE_URL);

// IP validation
$ip = filter_var('192.168.1.1', FILTER_VALIDATE_IP);
$ipv4 = filter_var('192.168.1.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
$ipv6 = filter_var('::1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);

// Boolean validation
var_dump(filter_var('yes', FILTER_VALIDATE_BOOLEAN));   // true
var_dump(filter_var('no', FILTER_VALIDATE_BOOLEAN));    // false
var_dump(filter_var('1', FILTER_VALIDATE_BOOLEAN));     // true
var_dump(filter_var('0', FILTER_VALIDATE_BOOLEAN));     // false
var_dump(filter_var('true', FILTER_VALIDATE_BOOLEAN));  // true
var_dump(filter_var('maybe', FILTER_VALIDATE_BOOLEAN)); // false
// With FILTER_NULL_ON_FAILURE:
var_dump(filter_var('maybe', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)); // null

Ловушка экзамена: filter_var('0', FILTER_VALIDATE_INT) возвращает 0 (int), а не false. Но 0 — falsy! Поэтому проверяйте результат СТРОГО: if (filter_var($val, FILTER_VALIDATE_INT) !== false). Аналогично для пустой строки и IP 0.0.0.0.

SANITIZE фильтры

<?php
declare(strict_types=1);

// SANITIZATION — cleans the input (removes unwanted characters)

// Remove HTML tags
$clean = filter_var('<p>Hello</p>', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
// '&lt;p&gt;Hello&lt;/p&gt;'

// Strip tags (DEPRECATED in PHP 8.1, use htmlspecialchars instead)
// $clean = filter_var('<p>Hello</p>', FILTER_SANITIZE_STRING);

// Remove non-numeric characters
$clean = filter_var('abc123def', FILTER_SANITIZE_NUMBER_INT);
// '123'

// Clean email
$clean = filter_var(' alice @test.com ', FILTER_SANITIZE_EMAIL);
// '[email protected]'

// Clean URL
$clean = filter_var('http://example.com/path with spaces', FILTER_SANITIZE_URL);

// Clean float
$clean = filter_var('$1,234.56', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
// '1234.56'

filter_input — получение данных из запроса

<?php
declare(strict_types=1);

// Safely get and validate input from superglobals
$email = filter_input(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);
$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 150],
]);
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT) ?: 1;

// Returns:
// - Value if valid
// - false if validation fails
// - null if variable does not exist

// Validate multiple inputs
$args = [
    'name' => FILTER_SANITIZE_FULL_SPECIAL_CHARS,
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => [
        'filter' => FILTER_VALIDATE_INT,
        'options' => ['min_range' => 1, 'max_range' => 150],
    ],
];
$data = filter_input_array(INPUT_POST, $args);

htmlspecialchars — защита от XSS

<?php
declare(strict_types=1);

$userInput = '<script>alert("XSS")</script>';

// ALWAYS escape output
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
// &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;

// Flags:
// ENT_QUOTES     — escape both double and single quotes
// ENT_SUBSTITUTE — replace invalid encoding with Unicode replacement char
// ENT_HTML5      — handle code as HTML5

// Helper function for templates
function e(string $value): string
{
    return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

// In templates:
echo '<p>' . e($user->name) . '</p>';

Запомни: ВСЕГДА экранируйте пользовательский ввод при выводе в HTML. Используйте htmlspecialchars() с флагами ENT_QUOTES | ENT_SUBSTITUTE и кодировкой UTF-8. Это основная защита от XSS-атак.

Правило валидации

  1. Validate (проверить) — данные соответствуют ожиданиям?
  2. Sanitize (очистить) — удалить опасные символы
  3. Escape (экранировать) — при выводе в контекст (HTML, SQL, JS)
<?php
declare(strict_types=1);

// Best practice: validate early, sanitize on input, escape on output
function processForm(): array
{
    $errors = [];

    $name = trim($_POST['name'] ?? '');
    if (empty($name) || mb_strlen($name) > 255) {
        $errors[] = 'Name is required (max 255 chars)';
    }

    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    if ($email === false || $email === null) {
        $errors[] = 'Valid email is required';
    }

    $age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT, [
        'options' => ['min_range' => 1, 'max_range' => 150],
    ]);
    if ($age === false || $age === null) {
        $errors[] = 'Valid age (1-150) is required';
    }

    return $errors;
}

Вопросы с экзамена ZCE

Проверь себя

5 из 6

Для чего нужна санитизация?

Какой флаг нужен для `htmlspecialchars` для экранирования одинарных кавычек?

Какая функция используется для получения определённой внешней переменной по имени и её опциональной фильтрации?

Что вернёт `filter_input(INPUT_GET, 'missing')` если параметра нет?

Что вернёт `filter_var('0', FILTER_VALIDATE_INT)`?