W3docs

PHP Filter

Расширение filter в PHP: валидация и санитизация, filter_var(), filter_input(), константы FILTER_VALIDATE_* и FILTER_SANITIZE_*, флаги.

Расширение filter в PHP — это встроенный инструмент для проверки и очистки данных, поступающих извне скрипта: из полей форм, строк запросов, cookies и HTTP-заголовков. Поскольку эти данные контролируются пользователем (а иногда и злоумышленником), им никогда нельзя доверять напрямую. На этой странице объясняется разница между валидацией и санитизацией, описаны основные функции (filter_var() и filter_input()), наиболее полезные константы фильтров и типичные ошибки.

Валидация и санитизация

Расширение filter выполняет две разные задачи, и их путаница — самая распространённая ошибка:

  • Валидацияпроверяет, соответствует ли значение правилу, и возвращает значение при успехе или false при неудаче. Значение никогда не изменяется. Используйте фильтры FILTER_VALIDATE_*.
  • Санитизацияудаляет или экранирует недопустимые символы и возвращает очищенную строку. Она не сообщает, было ли входное значение «правильным». Используйте фильтры FILTER_SANITIZE_*.

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

filter_var() — фильтрация одной переменной

filter_var() — основная рабочая функция. Она принимает значение, константу фильтра и необязательные параметры:

filter_var(mixed $value, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed

Валидация

<?php
$email = "[email protected]";

if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "Email is valid\n";
} else {
    echo "Email is invalid\n";
}

// Numbers, URLs and IPs work the same way:
var_dump(filter_var("42", FILTER_VALIDATE_INT));        // int(42)
var_dump(filter_var("not-a-number", FILTER_VALIDATE_INT)); // bool(false)
var_dump(filter_var("https://w3docs.com", FILTER_VALIDATE_URL)); // string

Вывод:

Email is valid
int(42)
bool(false)
string(18) "https://w3docs.com"

Подводный камень: фильтры валидации возвращают false при неудаче, но 0 и "" тоже являются ложными значениями. filter_var("0", FILTER_VALIDATE_INT) возвращает int(0), что провалит простую проверку if. Сравнивайте с === false или передавайте FILTER_NULL_ON_FAILURE, чтобы неудачные проверки давали null и можно было использовать !== null.

Санитизация

<?php
$dirty = "  john (doe)@exa<>mple.com  ";
echo filter_var($dirty, FILTER_SANITIZE_EMAIL), "\n"; // [email protected]

$comment = "<script>alert(1)</script>Hi";
echo filter_var($comment, FILTER_SANITIZE_SPECIAL_CHARS), "\n";

Вывод:

[email protected]
&#60;script&#62;alert(1)&#60;/script&#62;Hi

Передача параметров и флагов

Многие фильтры принимают дополнительные параметры. Например, можно валидировать целое число только в заданном диапазоне:

<?php
$options = [
    "options" => ["min_range" => 1, "max_range" => 120],
];
var_dump(filter_var("130", FILTER_VALIDATE_INT, $options)); // bool(false)
var_dump(filter_var("25",  FILTER_VALIDATE_INT, $options)); // int(25)

Вывод:

bool(false)
int(25)

К полезным флагам относятся: FILTER_NULL_ON_FAILURE (возвращает null вместо false), FILTER_FLAG_STRIP_LOW (удаляет символы ниже ASCII 32), а также FILTER_FLAG_IPV6 / FILTER_FLAG_IPV4 для уточнения FILTER_VALIDATE_IP.

filter_input() — фильтрация данных запроса напрямую

filter_input() считывает значение из суперглобальной переменной (по имени) и фильтрует его за один шаг, так что вам не нужно обращаться к необработанному массиву $_POST / $_GET:

filter_input(int $type, string $var_name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed

$type — одна из констант: INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER или INPUT_ENV:

<?php
// In a real form handler:
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

if ($email === false) {
    echo "Please enter a valid email.";
} elseif ($email === null) {
    echo "The email field was not submitted.";
} else {
    echo "Got: $email";
}

Обратите внимание на три возможных результата: значение (прошло проверку), false (присутствует, но недействительно) или null (поле не было отправлено). Для фильтрации целой формы за один раз см. filter_var_array() и filter_input_array().

Часто используемые константы фильтров

ФильтрТипНазначение
FILTER_VALIDATE_EMAILвалидацияАдрес электронной почты
FILTER_VALIDATE_URLвалидацияURL
FILTER_VALIDATE_INT / FILTER_VALIDATE_FLOATвалидацияЦелые / дробные числа
FILTER_VALIDATE_IPвалидацияАдрес IPv4 / IPv6
FILTER_VALIDATE_BOOLEANвалидация"yes", "on", "1"true
FILTER_SANITIZE_EMAILсанитизацияУдаление недопустимых символов email
FILTER_SANITIZE_URLсанитизацияУдаление недопустимых символов URL
FILTER_SANITIZE_NUMBER_INTсанитизацияОставляет цифры и + -
FILTER_SANITIZE_SPECIAL_CHARSсанитизацияHTML-кодирование < > & " '

Устарело с PHP 8.1: FILTER_SANITIZE_STRING (и его псевдоним FILTER_SANITIZE_STRIPPED). Для экранирования вывода используйте htmlspecialchars(); для очистки входных данных предпочтительнее конкретный фильтр валидации с контекстно-зависимым экранированием в точке использования.

Когда стоит использовать расширение filter?

  • Проверка регистрационной формы или формы обратной связи перед сохранением — используйте совместно с PHP Form Validation и валидацией полей URL и e-mail.
  • Проверка того, что параметр id в строке запроса является положительным целым числом перед запросом к базе данных.
  • Чтение и проверка значений из cookies или $_SERVER.

Фильтрация дополняет, но не заменяет другие меры защиты: используйте подготовленные запросы (PHP MySQLi prepared statements) против SQL-инъекций и htmlspecialchars() при выводе пользовательских данных в HTML. Для правил на основе шаблонов, которые нельзя выразить средствами расширения filter, обратитесь к регулярным выражениям.

Практика

Практика
Чем помогает PHP Filters при работе с отправленными данными?
Чем помогает PHP Filters при работе с отправленными данными?
Was this page helpful?