Menu

PHP filter_var(): проверка email, int, URL и не только

filter_var($value, FILTER_VALIDATE_EMAIL) возвращает значение, если оно корректно, и false, если нет; так же работают FILTER_VALIDATE_INT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL и FILTER_VALIDATE_IP. Опции (min_range, default), флаги, фильтры очистки и ловушка false и 0.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

filter_var($value, FILTER_VALIDATE_EMAIL) возвращает значение, когда это корректный адрес email, и false, когда нет. Поменяйте фильтр, чтобы проверять другие форматы: FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_URL, FILTER_VALIDATE_BOOL, FILTER_VALIDATE_IP. Всегда сравнивайте результат через === false.

Два результата удивляют. ada@example отклоняется, потому что в домене нет точки, а ' ada@example.com' отклоняется из-за пробела в начале, поэтому обрезайте ввод через trim() перед проверкой.

Проверка email из формы

Та же проверка за формой. Запустите, введите адрес и нажмите Check; блок выполнится снова с вашим вводом в $_POST.

FILTER_VALIDATE_EMAIL проверяет только формат. nobody@example.com проходит, и адрес с опечаткой в домене тоже прошёл бы. Не-ASCII символы отклоняются: adä@example.com проходит только с FILTER_FLAG_EMAIL_UNICODE, который разрешает их до @, а домен вроде exämple.com не проходит даже с этим флагом, если сначала не преобразовать его в форму xn--. Единственный способ узнать, что адрес работает, это отправить на него ссылку для подтверждения.

Проверка целого числа с min_range и max_range

FILTER_VALIDATE_INT превращает корректную строку в int и отклоняет всё остальное. Массив опций добавляет диапазон и значение по умолчанию:

Пробелы вокруг и + в начале принимаются, ведущий ноль ('042') нет, а результат для '42' это целое 42, а не строка. Выход за диапазон даёт false; с опцией default вы получаете значение по умолчанию вместо false, что удобно для вещей вроде ?page= (смотрите GETи_GET и _POST). Добавьте FILTER_FLAG_ALLOW_HEX или FILTER_FLAG_ALLOW_OCTAL, чтобы принимать 0x1A или 0755.

Ловушка 0 и false

Корректное '0' возвращает целое 0, а 0 ложно. Простой if считает это неудачей:

То же касается FILTER_VALIDATE_FLOAT ('0.0') и FILTER_VALIDATE_BOOL, где false это допустимый ответ. Для этого и существует FILTER_NULL_ON_FAILURE.

Логические значения, float, URL и IP-адреса

FILTER_VALIDATE_BOOL это имя из PHP 8; FILTER_VALIDATE_BOOLEAN тот же фильтр. Без FILTER_NULL_ON_FAILURE 'maybe' вернуло бы false, неотличимое от 'off'.

Корректный URL ещё не безопасная ссылка

FILTER_VALIDATE_URL проверяет, что строка по форме похожа на URL, с любой схемой. Сюда входят и схемы, которые вы никогда не хотите видеть в href:

javascript://comment%0Aalert(1) проходит FILTER_VALIDATE_URL, и браузер выполняет его как JavaScript при нажатии на ссылку, потому что %0A завершает //comment. Проверяйте схему через parse_url(), прежде чем выводить URL пользователя на страницу. Можно также требовать отдельные части через FILTER_FLAG_PATH_REQUIRED и FILTER_FLAG_QUERY_REQUIRED.

Фильтры очистки

Фильтры очистки удаляют символы, а не отвечают "да" или "нет". Они полезны, чтобы нормализовать ввод, а не чтобы сделать его безопасным для вывода:

Посмотрите на первую строку: Order #12-345 (x2) превращается в 12-3452, число, которого никогда не было во вводе, а третья строка это адрес, который никто не вводил. Если очищаете, потом проверяйте результат. Для всего, что выводится в HTML, правильный инструмент это htmlspecialchars() при выводе (FILTER_SANITIZE_FULL_SPECIAL_CHARS делает то же экранирование). FILTER_SANITIZE_STRING устарел с PHP 8.1; чем его заменить, смотрите в htmlspecialchars.

Проверка всей формы через filter_var_array

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

role исчез: ключи, которых нет в списке, отбрасываются, и это не даёт посетителю добавить role=admin к форме и сохранить его. country равен null, потому что его не отправили. На веб-сервере filter_input_array(INPUT_POST, $rules) делает то же самое, читая прямо из запроса.

Часто задаваемые вопросы

Как проверить адрес email в PHP?

Используйте filter_var($email, FILTER_VALIDATE_EMAIL), которая возвращает строку email, если она корректна, и false, если нет: if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) { /* invalid */ }. Она проверяет только формат; чтобы узнать, существует ли адрес, отправьте письмо с подтверждением.

Как проверить, что строка это целое число, в PHP?

filter_var($s, FILTER_VALIDATE_INT) возвращает int для "42", "-7" и " 42 " и false для "4.2", "42abc" или "042". Сравнивайте через !== false, потому что корректное "0" возвращает 0, а это ложное значение.

Почему filter_var возвращает false для 0?

Не возвращает: filter_var('0', FILTER_VALIDATE_INT) возвращает целое 0. Ошибка в проверке if (filter_var(...)), которая считает 0 таким же, как false. Пишите if (filter_var($v, FILTER_VALIDATE_INT) !== false).

Что заменило FILTER_SANITIZE_STRING в PHP 8.1?

Прямой замены нет; фильтр объявили устаревшим, потому что его имя обещало безопасность, которой он не давал. Проверяйте ожидаемый ввод, храните его как есть и экранируйте при выводе через htmlspecialchars(). Если нужно удалить теги, используйте strip_tags().

Чем filter_var отличается от filter_input?

filter_var() фильтрует любое переданное значение. filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT) читает прямо из исходного запроса, поэтому возвращает null, когда параметра нет, и игнорирует любые изменения, которые ваш код внёс в $_GET. Обе принимают одинаковые фильтры и опции.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ