Фильтрация переменных в 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;
?>
<script>alert(1)</script>
Этот фильтр предотвращает 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<script>
)
Невалидное значение 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