W3docs

Валидация 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:

php— editable, runs on the server

Поскольку filter_var возвращает false (не null) для некорректных данных, всегда сравнивайте с помощью свободного ! или строгого === false. Распространённая ошибка — написать if (filter_var($email, FILTER_VALIDATE_EMAIL) == false) для адреса вроде 0, что в данном случае допустимо, но в целом лучше использовать === false, чтобы избежать сюрпризов нестрогого сравнения PHP.

Валидация Email с помощью регулярного выражения

Email можно также проверить с помощью регулярного выражения — шаблона, описывающего допустимые строки — используя preg_match. Это полезно знать, но прибегайте к нему лишь тогда, когда нужно правило, которое filter_var не может выразить (например, ограничение одним корпоративным доменом):

php— editable, runs on the server

Примечание: В продакшне предпочитайте 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://.

php— editable, runs on the server

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 можно сопоставить с помощью регулярного выражения. Приведённый ниже шаблон носит разрешительный характер и лучше воспринимается как учебный пример, а не правило для продакшна:

php— editable, runs on the server

Примечание: Для обоих случаев — 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 для ужесточения правила.
  • Регулярные выражения тоже могут проверять эти форматы, но в них легко ошибиться — предпочитайте встроенные фильтры.
  • Валидация и санитизация — разные задачи; применяйте обе и считайте все отправленные данные ненадёжными.

Практика

Практика
Какие из следующих утверждений о PHP-формах, URL и E-mail верны?
Какие из следующих утверждений о PHP-формах, URL и E-mail верны?
Was this page helpful?