Валидация формы - это процедура фильтрации и проверки данных, передаваемых серверу при отправке формы. Например, для нашей формы обратной связи мы хотим сделать следующие проверки:
22) Злоумышленники могут вставлять HTML-код в сообщение. Если вы откроете такой код в браузере, вы можете увидеть нежелательное содержимое. Чтобы этого избежать, нужно заменить HTML-теги в теме сообщения и тексте.
Требования выше называются правилами валидации. Эти правила могут быть разделены на две категории: фильтры и валидаторы.
Фильтры изменяют введенные пользователем данные, чтобы исправить возможные ошибки или обеспечить соответствие данных определенному формату. Фильтры, как правило, применяются первыми, а валидаторы - последними.
Валидаторы проверяют, допустимы ли данные. Если все введенные данные корректны, форма считается действительной, и данные могут безопасно использоваться уровнем бизнес-логики. Если какое-то поле недействительно, валидатор устанавливает флаг ошибки. В этом случае, форма, как правило, снова показывается пользователю, и тому предлагается исправить ошибки ввода и переслать форму на сервер.
Что произойдет, если я не добавлю правило валидации для определенного поля формы?
Если вы не добавите правило валидации, отправленное пользователем значение не будет проверено, тем самым оставив дыру в безопасности вашего сайта. Рекомендуется всегда добавлять правило валидации для каждого поля формы, заполняемого пользователем, а также добавлять столько проверок каждому полю, сколько нужно для поддержания безопасности сайта.
В ZF3 правила валидации хранятся с помощью класса InputFilter
. Этот класс определяется
в компоненте Zend\InputFilter
. Фильтр входных данных - это контейнер для так называемых входов (inputs).
Как правило, вы добавляете входы для каждого поля модели.
Входы могут состоять из фильтров и/или валидаторов и некоторой дополнительной информации. Например, в них может содержаться флаг, указывающий на то, обязательно ли это поле, или его значение может отсутствовать в HTTP-запросе.
Аналогично добавлению полей модели формы, существует два способа добавить входы в фильтр:
либо через передачу экземпляра класса ввода в качестве аргумента его метода add()
, либо через передачу
описания в виде массива 23. В следующем разделе мы опишем второй способ (он более предпочтителен,
так как требует меньшего количества кода).
23) Во втором случае (описание в виде массива) вход будет автоматически создан
с помощью класса Zend\InputFilter\Factory
.
Чтобы добавить вход в фильтр, используйте метод `add(), который принимает описание входа в виде массива следующим образом:
[
'name' => '<name>',
'type' => '<type>',
'required' => <required>,
'filters' => [
// Добавьте конфигурацию фильтров ...
],
'validators' => [
// Добавьте конфигурацию валидаторов ...
]
]
Этот массив содержит следующие ключи:
Ключ name
определяет имя входа. Оно должно совпадать с именем поля модели формы.
В противном случае, правило валидации не будет применяться к полю.
Ключ type
(строка 3) определяет имя класса входа. Этот ключ опционален.
По умолчанию (когда этот ключ пропущен) используется класс Zend\InputFilter\Input
.
Доступные классы входов показаны на рисунке 7.16.: класс Input
предназначен для
использования с обычными скалярными значениями, ArrayInput
используется для
фильтрации/валидации значений массива, а FileInput
- для проверки загружаемых файлов.
Ключ required
(строка 4) сообщает, является поле формы обязательным или опциональным.
В первом случае пользователь должен будет его заполнить, иначе появится сообщение об
ошибке валидации.
Ключи filters
(строка 5) и validators
(строка 8) могут содержать конфигурацию для
одного или нескольких (или нуля) фильтров и/или валидаторов поля модели формы.
Типичная конфигурация фильтра представлена ниже:
[
'name' => '<filter_name>',
'priority' => <priority>,
'options' => [
// Здесь идут опции фильтра ...
]
],
Ключ name
(строка 2) - это имя фильтра. Это может быть либо полностью определенное имя
класса фильтра (например, StringTrim::class
) либо псевдоним (например, StringTrim
).
Опциональный ключ priority
(строка 3) определяет приоритет в списке фильтров. Это должно
быть число типа integer. Фильтры с наивысшем приоритетом будут применены первыми. По умолчанию
присваивается константа FilterChain::DEFAULT_PRIORITY
(со значением 1000).
Массив options
(строка 4), индивидуальный для каждого фильтра, может содержать параметры для настройки.
Типичная конфигурация валидатора представлена ниже:
[
'name' => '<validator_name>',
'break_chain_on_failure' => <flag>,
'options' => [
// Здесь идут опции валидатора ...
]
],
Ключ name
(строка 2) - это имя валидатора. Это может быть либо полностью определенное имя
класса валидатора (например, `EmailAddress::class
) либо псевдоним (например, EmailAddress
).
Опциональный ключ break_chain_on_failure
(строка 3) определяет поведение в случае неудачной проверки.
При значении true
, последующие валидаторы в списке не будут выполняться; в противном случае каждый
валидатор в списке будет выполняться вне зависимости от результата других валидаторов.
Массив options
(строка 4), индивидуальный для каждого валидатора, может содержать параметры для настройки.
Теперь, когда у вас есть общее представление о том, как заполнять фильтр входных данных фильтрами и валидаторами для каждого поля формы, давайте дополним наш
класс модели формы ContactForm
. В фрагменте кода ниже мы добавим метод addInputFilter()
,
который определяет правила фильтрации/валидации, хранит их в фильтре входных данных и добавляет
фильтр к модели формы:
<?php
// ...
use Zend\InputFilter\InputFilter;
class ContactForm extends Form
{
public function __construct()
{
// ... вызовите этот метод для добавления правил валидации
$this->addInputFilter();
}
// ...
// Этот метод создает фильтр входных данных (используемый для фильтрации/валидации).
private function addInputFilter()
{
// Используем стандартный InputFilter формы
$inputFilter = $this->getInputFilter();
$inputFilter->add([
'name' => 'email',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
],
'validators' => [
[
'name' => 'EmailAddress',
'options' => [
'allow' => \Zend\Validator\Hostname::ALLOW_DNS,
'useMxCheck' => false,
],
],
],
]);
$inputFilter->add([
'name' => 'subject',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
['name' => 'StripTags'],
['name' => 'StripNewlines'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 128
],
],
],
]);
$inputFilter->add([
'name' => 'body',
'required' => true,
'filters' => [
['name' => 'StripTags'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 4096
],
],
],
]);
}
}
В этом фрагменте первым делом мы объявляем псевдоним для класса Zend\InputFilter\InputFilter
(строка 3).
В конструкторе модели формы (строка 10), мы вызываем метод addInputFilter()
, который определяется
в строках 16-76.
Задача метода addInputFilter()
- добавить правила фильтрации/валидации (строки 21-75). Чтобы добавить правила фильтрации/валидации в фильтр, используется метод add()
класса
InputFilter
, принимающий описание входа, который нужно создать, в виде массива.
Мы добавляем три входа (по одному для каждого поля нашей модели формы, кроме кнопки отправки формы):
Для поля email
мы устанавливает флаг required
на значение true
, чтобы сделать заполнение
этого поля обязательным. Мы используем фильтр StringTrim, чтобы убрать пробелы из начала и конца
адреса электронной почты; и валидатор @
EmailAddress для проверки введенного пользователем адреса
на корректность. Мы настраиваем валидатор @
EmailAddress так, чтобы разрешать использованием доменных
имен в качестве адресов эл. почты (флаг
\Zend\Validator\Hostname::ALLOW_DNS) и отключаем проверку
MX-записи (устанавливаем опцию
useMxCheck на
false`).
Поле subject
мы аналогичным образом делаем обязательным, а затем используем фильтр StringTrim
для удаления пробелов из начала и конца. Кроме этого мы используем фильтры StripNewlines
и StripTags
, чтобы отфильтровать соответственно символы перевода строки и HTML-теги.
Используя валидатор StringLength
мы ограничиваем длину строки темы - от 1 до 128 символов.
Поле body
мы также делаем обязательным, и используем фильтр StripTags
, чтобы убрать HTML-теги
из основного текста. Помимо этого, мы с помощью валидатора StringLength
ограничиваем текст
электронного сообщения - от 1 до 4096 символов.
На рисунке 7.17 представлено схематическое графическое представление созданного нами фильтра входных данных.
Выше мы вкратце описали, как создавать фильтр входных данных для модели формы. За более детальной информацией об упомянутых выше (и других) фильтрах и валидаторах, а также за примерами их использования, обратитесь к главам Преобразование данных с помощью фильтров и Проверка входных данных с помощью валидаторов.