Валидация PHP-форм: URL и Email
Как проверять email и URL в PHP-формах с помощью filter_var и регулярных выражений — надёжно и читаемо.
Email и URL — два наиболее часто встречающихся поля в любой веб-форме, и именно в них пользователи чаще всего допускают ошибки. Опечатка вроде user@example (отсутствует домен верхнего уровня) или example.com (URL без схемы) пройдёт простую проверку «поле не пустое», но сломается в тот момент, когда приложение попытается отправить письмо или перейти по ссылке.
В этой главе показано, как валидировать поля email и URL в PHP — убеждаться, что значение имеет правильный формат, прежде чем сохранять или использовать его. Валидация — один из шагов общего процесса, который также включает получение данных из $_POST/$_GET, их очистку и санитизацию; полную картину см. в Обработка форм в PHP и Валидация форм в PHP.
Рассматриваются два подхода: встроенная функция filter_var (рекомендуется) и регулярные выражения (полезно знать, иногда необходимы для нестандартных правил).
Валидация поля Email
Самый простой способ проверить адрес электронной почты в PHP — функция filter_var с фильтром FILTER_VALIDATE_EMAIL. Она возвращает отфильтрованное значение, если строка похожа на корректный email, и false в противном случае — поэтому она естественно сочетается с проверкой через if:
Поскольку filter_var возвращает false (не null) для некорректных данных, всегда сравнивайте с помощью свободного ! или строгого === false. Распространённая ошибка — написать if (filter_var($email, FILTER_VALIDATE_EMAIL) == false) для адреса вроде 0, что в данном случае допустимо, но в целом лучше использовать === false, чтобы избежать сюрпризов нестрогого сравнения PHP.
Валидация Email с помощью регулярного выражения
Email можно также проверить с помощью регулярного выражения — шаблона, описывающего допустимые строки — используя preg_match. Это полезно знать, но прибегайте к нему лишь тогда, когда нужно правило, которое filter_var не может выразить (например, ограничение одним корпоративным доменом):
Примечание: В продакшне предпочитайте
FILTER_VALIDATE_EMAILсамописным регулярным выражениям. Полная спецификация email (RFC 5322) печально известна сложностью сопоставления с помощью единственного шаблона, а приведённое выше регулярное выражение отклонит вполне допустимые адреса — например, с длинными доменами верхнего уровня (.museum) или адреса с тегом+([email protected]). См. Регулярные выражения в PHP, если хотите разобраться в синтаксисе шаблонов.
Валидация поля URL
URL проверяются аналогично — с помощью filter_var и фильтра FILTER_VALIDATE_URL. Важный момент: фильтр требует наличия схемы (http://, https://, ftp://, …). Голое значение example.com или www.example.com считается недопустимым, поэтому заранее решите, ожидает ли ваша форма, что пользователи будут вводить префикс https://.
FILTER_VALIDATE_URL принимает дополнительные флаги для ужесточения правила — например, FILTER_FLAG_PATH_REQUIRED (URL должен содержать путь после хоста) или FILTER_FLAG_QUERY_REQUIRED (должен содержать строку запроса):
<?php
$url = "https://example.com/page?ref=newsletter";
if (filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED)) {
echo "Valid URL with a query string";
} else {
echo "Missing or invalid query string";
}
?>Валидация URL с помощью регулярного выражения
Как и в случае с email, URL можно сопоставить с помощью регулярного выражения. Приведённый ниже шаблон носит разрешительный характер и лучше воспринимается как учебный пример, а не правило для продакшна:
Примечание: Для обоих случаев — email и URL — встроенные фильтры
filter_varявляются рекомендуемым выбором. Они поддерживаются вместе с PHP, охватывают граничные случаи, которые пропускают регулярные выражения, и делают код значительно читаемее.
Объединяем всё в форму
В реальной форме вы работаете не с жёстко заданными строками — вы читаете отправленные значения из суперглобального массива $_POST, обрезаете пробелы и собираете ошибки, чтобы вывести их все разом. Следующий пример проверяет обязательный email и необязательный сайт:
<?php
// Imagine these come from a submitted <form method="post">.
$email = trim($_POST["email"] ?? "");
$website = trim($_POST["website"] ?? "");
$errors = [];
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = "Please enter a valid email address.";
}
// Website is optional: only validate it when something was typed.
if ($website !== "" && !filter_var($website, FILTER_VALIDATE_URL)) {
$errors[] = "Please enter a valid URL.";
}
if (empty($errors)) {
echo "All inputs are valid.";
} else {
echo implode("\n", $errors);
}
?>Оператор объединения с null ?? "" позволяет избежать предупреждения, если поле отсутствует, а проверка $website !== "" делает URL необязательным. Этот же паттерн используется в Обязательные поля PHP-форм.
Валидация и санитизация
Валидация отвечает на вопрос «правильный ли формат у этого значения?» — она не удаляет и не экранирует опасные символы. Это задача санитизации. PHP предоставляет санитизирующие фильтры, например FILTER_SANITIZE_EMAIL, который удаляет символы, недопустимые в адресе электронной почты:
<?php
$raw = "user(at)example.com";
$clean = filter_var($raw, FILTER_SANITIZE_EMAIL); // "useratexample.com"
if (filter_var($clean, FILTER_VALIDATE_EMAIL)) {
echo "Usable email: $clean";
} else {
echo "Could not produce a valid email";
}
?>Здесь санитизация превращает user(at)example.com в useratexample.com, который затем не проходит валидацию — именно такой результат и нужен, поскольку исходное значение не являлось настоящим адресом. Правило таково: валидируйте, чтобы принять или отклонить; санитизируйте перед выводом; никогда не доверяйте данным из формы. Для экранирования данных при вставке в HTML или базу данных см. htmlspecialchars и mysqli::real_escape_string.
Итоги
- Используйте
filter_var($value, FILTER_VALIDATE_EMAIL)иfilter_var($value, FILTER_VALIDATE_URL)для надёжной и читаемой валидации. FILTER_VALIDATE_URLтребует схемы, напримерhttps://; добавляйте флаги вродеFILTER_FLAG_PATH_REQUIREDдля ужесточения правила.- Регулярные выражения тоже могут проверять эти форматы, но в них легко ошибиться — предпочитайте встроенные фильтры.
- Валидация и санитизация — разные задачи; применяйте обе и считайте все отправленные данные ненадёжными.