Фильтрация переменных в PHP с помощью filter_var: полное руководство

Раздел: Безопасность и валидация -> Обработка входных данных

filter_var: фильтрация переменных в PHP

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

Основное эффективное решение: универсальный filter_var с флагами

Наиболее гибкий подход – использовать filter_var() с одним из предопределенных фильтров и, при необходимости, дополнительными опциями. Это позволяет заменить множество отдельных проверок (is_numeric, preg_match, htmlspecialchars и т.д.) одной функцией.


<?php
$email = 'user@example.com';
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo 'Email корректен';
} else {
    echo 'Email некорректен';
}
?>
    

Php filter var (filter_var - фильтрация переменной в php)

Email корректен

Код проверяет, является ли строка допустимым email-адресом. Если адрес не соответствует формату, функция возвращает false.

Типичная ошибка: забыть проверить возвращаемое значение на false. Если фильтр возвращает false, это не всегда означает ошибку – значение может быть валидным, но преобразованным (например, FILTER_SANITIZE_NUMBER_INT возвращает строку). Всегда используйте строгое сравнение (===) для валидации.

Варианты решений и частные случаи

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

Используйте фильтр FILTER_VALIDATE_INT и опции min_range / max_range.


<?php
$age = 25;
$options = ['options' => ['min_range' => 18, 'max_range' => 120]];
if (filter_var($age, FILTER_VALIDATE_INT, $options)) {
    echo 'Возраст прошел проверку';
} else {
    echo 'Некорректный возраст';
}
?>
    
Возраст прошел проверку

Как удалить все символы, кроме цифр, из строки?

Примените санитирующий фильтр FILTER_SANITIZE_NUMBER_INT. Он оставляет только цифры и знак минус.


<?php
$phone = '+7 (123) 456-78-90';
$clean = filter_var($phone, FILTER_SANITIZE_NUMBER_INT);
echo $clean;
?>
    
+71234567890

Обратите внимание: плюс сохраняется, так как он не является цифрой, но считается частью формата номера. Для полной очистки только цифр можно дополнительно удалить знаки.

Как экранировать строку для безопасного вывода в HTML?

Используйте FILTER_SANITIZE_FULL_SPECIAL_CHARS – он преобразует специальные HTML-символы в сущности (аналог htmlspecialchars).


<?php
$input = '<script>alert(1)</script>';
$safe = filter_var($input, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
echo $safe;
?>
    
&lt;script&gt;alert(1)&lt;/script&gt;

Этот фильтр предотвращает XSS-атаки при выводе данных в браузер.

Как проверить, что строка является корректным URL?

Фильтр FILTER_VALIDATE_URL проверяет синтаксис URL в соответствии с RFC.


<?php
$url = 'https://example.com/path?q=1';
if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo 'URL корректен';
} else {
    echo 'URL некорректен';
}
?>
    
URL корректен

По умолчанию проверяется наличие схемы (http/https/ftp и т.д.).

Как фильтровать массив данных с разными типами?

Используйте filter_var_array() – передайте массив значений и массив определений фильтров.


<?php
$data = [
    'email' => 'user@example.com',
    'age' => '25',
    'name' => 'John<script>'
];
$filters = [
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 100]],
    'name' => FILTER_SANITIZE_FULL_SPECIAL_CHARS
];
$result = filter_var_array($data, $filters);
print_r($result);
?>
    
Array
(
    [email] => user@example.com
    [age] => 25
    [name] => John&lt;script&gt;
)
    

Невалидное значение email вернет false, что можно обработать отдельно.

Распространенная ошибка: передача несуществующего фильтра. Убедитесь, что константа фильтра написана без опечаток. Также не все версии PHP поддерживают все фильтры (например, FILTER_VALIDATE_DOMAIN появился в PHP 7.0).

Проблемы при использовании filter_var и способы их решения

  • Ложное срабатывание валидации: FILTER_VALIDATE_EMAIL может пропускать некоторые нестандартные, но технически корректные адреса (например, с тегом +). Для строгой проверки лучше комбинировать с регулярным выражением.
  • Уязвимость в санитизации: FILTER_SANITIZE_STRING (устарел в PHP 8.1) удаляет теги, но не экранирует. Используйте FILTER_SANITIZE_FULL_SPECIAL_CHARS для вывода.
  • Проблемы с кодировкой: filter_var не меняет кодировку. Если входные данные в UTF-8, но фильтр ожидает однобайтовую строку, возможны артефакты. Всегда нормализуйте кодировку заранее.

Если фильтр возвращает false, это может означать как ошибку валидации, так и технический сбой. Рекомендуется дополнительно проверять значение через is_bool($result) и отслеживать ошибки через error_get_last().

Цели и случаи использования filter_var

  • Валидация входных данных из форм (email, URL, числа).
  • Санитизация пользовательского ввода перед сохранением в БД или выводом на экран.
  • Пакетная обработка массивов данных через filter_var_array.
  • Быстрая замена устаревших функций (ereg, mysql_real_escape_string) безопасными встроенными средствами.
  • Создание собственных фильтров через FILTER_CALLBACK для нестандартной логики.

filter_var не заменяет полную проверку бизнес-логики, но служит первым уровнем защиты от некорректных или опасных данных.

Расширенные примеры использования filter_var

1. Проверка доменного имени (FILTER_VALIDATE_DOMAIN)

Фильтр появился в PHP 7.0. Проверяет, является ли строка валидным доменом.

Пример

<?php
$domains = ['example.com', 'sub.domain.org', 'not_a_domain', '127.0.0.1'];
foreach ($domains as $d) {
    if (filter_var($d, FILTER_VALIDATE_DOMAIN)) {
        echo "$d - валидный домен\n";
    } else {
        echo "$d - не валидный домен\n";
    }
}
?>
example.com - валидный домен
sub.domain.org - валидный домен
not_a_domain - не валидный домен
127.0.0.1 - не валидный домен

Фильтр не проверяет существование домена в DNS, только синтаксис.

2. Фильтрация IP-адреса с проверкой диапазона (FILTER_VALIDATE_IP + флаги)

Пример

<?php
$ip = '192.168.1.1';
$flags = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE; // исключает частные диапазоны
if (filter_var($ip, FILTER_VALIDATE_IP, $flags)) {
    echo 'IP корректен и не является частным';
} else {
    echo 'IP некорректен или является частным';
}
?>
IP некорректен или является частным

Флаг FILTER_FLAG_NO_PRIV_RANGE отбрасывает адреса из диапазонов 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.

3. Санитизация чисел с плавающей точкой (FILTER_SANITIZE_NUMBER_FLOAT)

Пример

<?php
$price = '$ 1,234.56';
$clean = filter_var($price, FILTER_SANITIZE_NUMBER_FLOAT, ['flags' => FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND]);
echo $clean;
?>
1234.56

Фильтр удаляет всё, кроме цифр, точки (флаг FRACTION) и запятой (флаг THOUSAND). Результат – строка, которую можно преобразовать в float.

4. Использование FILTER_CALLBACK для сложной логики проверки

Пример

<?php
function valid_username($value) {
    // Пользовательская проверка: только буквы, цифры и подчеркивания, длина 3-20
    return preg_match('/^[a-zA-Z0-9_]{3,20}$/', $value) ? $value : false;
}

$username = 'test_user123';
$result = filter_var($username, FILTER_CALLBACK, ['options' => 'valid_username']);
var_dump($result);
?>
string(14) "test_user123"

Если бы имя содержало пробел или было слишком коротким, вернулся бы false.

5. Пакетная фильтрация входных данных из $_POST с filter_input_array

Функция filter_input_array() позволяет применить фильтры непосредственно к суперглобальным массивам.

Пример

<?php
// Предположим, $_POST = ['email' => 'test@test', 'age' => 'abc']
$filters = [
    'email' => FILTER_VALIDATE_EMAIL,
    'age' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1]]
];
$result = filter_input_array(INPUT_POST, $filters);
print_r($result);
?>
Array
(
    [email] => false
    [age] => false
)

email не прошел валидацию, т.к. не содержит точки после @. age false, т.к. 'abc' не число.

6. Комбинированная санитизация и валидация для одного поля

Иногда нужно сначала очистить, потом проверить. Делается последовательно.

Пример

<?php
$input = ' user@example.com  ';
$sanitized = filter_var($input, FILTER_SANITIZE_EMAIL); // удаляет пробелы и недопустимые символы
echo "После санитизации: '$sanitized'\n";
if (filter_var($sanitized, FILTER_VALIDATE_EMAIL)) {
    echo 'Валидация пройдена';
} else {
    echo 'Валидация не пройдена';
}
?>
После санитизации: 'user@example.com'
Валидация пройдена

FILTER_SANITIZE_EMAIL удаляет все символы, недопустимые в email-адресе (пробелы, управляющие символы, некоторые спецсимволы).

7. Работа с кодировкой и фильтр FILTER_FLAG_STRIP_HIGH

Для удаления многобайтовых символов (не ASCII) из строки.

Пример

<?php
$text = "Привет, мир! Hello, world!";
$ascii = filter_var($text, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH); // устарел, но для примера
echo $ascii;
?>
, ! Hello, world!

Все кириллические символы удалены. В современных версиях PHP лучше использовать iconv или mb_convert_encoding.

8. Использование filter_var с некорректными данными и обработка ошибок

Пример

<?php
$email = 'not.an.email';
$result = filter_var($email, FILTER_VALIDATE_EMAIL);
if ($result === false) {
    // Дополнительно можно получить предупреждение через error_get_last
    $error = error_get_last();
    echo "Ошибка валидации: " . ($error['message'] ?? 'unknown');
} else {
    echo "Email корректен: $result";
}
?>
Ошибка валидации: filter_var(): Email validation failed

Предупреждение генерируется только при включенном выводе ошибок. В production лучше подавлять и проверять возвращаемое значение.

9. Фильтр FILTER_VALIDATE_BOOLEAN для проверки логических значений

Пример

<?php
$vals = ['true', 'false', '1', '0', 'yes', 'on', 'off', 'maybe'];
foreach ($vals as $v) {
    $res = filter_var($v, FILTER_VALIDATE_BOOLEAN, ['flags' => FILTER_NULL_ON_FAILURE]);
    echo "$v => ";
    var_dump($res);
}
?>
true => bool(true)
false => bool(false)
1 => bool(true)
0 => bool(false)
yes => bool(true)
on => bool(true)
off => bool(false)
maybe => NULL

Флаг FILTER_NULL_ON_FAILURE заставляет возвращать null вместо false, если значение не может быть интерпретировано как булево.

10. Фильтрация макроса URL с проверкой наличия query-параметров

Комбинируем filter_var с разбором URL.

Пример

<?php
$url = 'https://example.com/page?name=John&age=30';
$valid = filter_var($url, FILTER_VALIDATE_URL);
if ($valid) {
    $parts = parse_url($valid);
    if (isset($parts['query'])) {
        parse_str($parts['query'], $params);
        echo 'Параметры: ' . implode(', ', array_keys($params));
    } else {
        echo 'Нет параметров';
    }
}
?>
Параметры: name, age

filter_var - фильтрация переменной в PHP - comments

En
Php filter var (php)