Zend_Filter_Input совершенно незаслуженно был обойдён вниманием со стороны разработчиков. На практике он способен во многих ситуациях заменить уже ставший привычным Zend_Form.
Что это и зачем оно нам?
Процитирую документацию:
Zend_Filter_Input предоставляет интерфейс для объединения фильтров и валидаторов, применяемых к коллекциям данных, и возвращает переданные значения после того, как они обработаны фильтрами и валидаторами.
Таким образом, мы передаём в Zend_Filter_Input данные, они нужным нам образом обрабатываются, и получаем мы уже проверенные данные. Если данные не прошли валидацию, мы получаем сообщения об ошибках. Обработка данных состоит из трёх элементов:
- Фильтры
- Основная задача – вырезать некорректные данные. Например, теги, или же недопустимые символы. Ознакомиться со стандартными фильтрами.
- Валидаторы
- Валидаторы занимаются проверкой данных на корректность. Их отличие от фильтров в том, что они не изменяют исходные данные. Например, валидатор Zend_Validate_Alpha не пропустит строку ‘foo123′, выдав сообщение об ошибке. В это же время фильтр Zend_Filter_Alpha просто вырежет лишнее, оставив строку ‘foo’. Стандартные валидаторы.
- Эскейперы
- Эскейперы занимаются преобразованием данных в корректные значения. Например, замена символов < и > на соответствующие HTML-сущности. В отличие от фильтров, они не просто удаляют некорректные значения, а заменяют их на допустимое.
Благодаря Zend_Filter_Input, мы можем объединить фильтры, валидаторы и эскейперы для обработки нужных нам данных.
Как мы можем это использовать?
Следуя мудрости предков, я лучше покажу вам пример, чем буду объяснять элементарные вещи словами.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | $filters = array(); $validators = array( 'firstName' => array( 'Alpha', // Zend_Validate_Alpha array('StringLength', 3, 20), // Zend_Validate_StringLength 'presence'=>'required' // обязательный параметр ), 'lastName' => array( 'Alpha', array('stringLength', 3, 30); ), 'email' => array( 'EmailAddress', 'presence'=>'required' //обязательный параметр ), 'password' => array( 'StringEquals', 'fields' => array('password', 'password-confirm') ) ); $options = array('escapeFilter' => 'StringTrim'); $input = new Zend_Fiter_Input($filters, $validators, $_POST, $options); if ($input->isValid()) { $firstName = $input->firstName; // обработанное эскейпером значение (в нашем случае StringTrim) $lastName = $input->getUnescaped('firstName'); //необработанное эскейпером значение $email = $Input->getEscaped('email'); // ещё один способ получить обработанное эскейпером значение // записываем в БД } else { $errorsMessages = $input->getMessages(); // информируем пользователя об ошибках } |
Как видите, всё просто. Не так громоздко, как использование Zend_Form, особенно когда он не нужен.
Но следует рассказать про несколько тонкостей, с которыми я столкнулся.
- Используемый по умолчанию эскейпер – Zend_Filter_HtmlEntities. Мне неизвестно, почему разработчики так поступили, но я всегда заменяю его на Zend_Filter_StringTrim.
- Для локализации сообщений об ошибках можно использовать те же способы, что и для Zend_Form/Zend_Validate. Я обычно сохраняю Zend_Translate-адаптер в Zend_Registry с именем “Zend_Translate”
Если интересно – могу расширить тему, оставляйте пожелания в комментариях.
Имейте в виду, это лишь вводная статья. Подробности ищите в документации по Zend Framework.
power man says:
Лично я столкнулся с одной проблемой. А именно кодировка получаемых данных после $Input->getEscaped(‘email’); если у нас utf-8 и строка написана на русском. В итоге решение оказалось простым.
17 февраля 2009, 4:04$data = new Zend_Filter_Input($this->_filters, $this->_validators, $data);
$data->setDefaultEscapeFilter(new Zend_Filter_HtmlEntities(ENT_COMPAT, ‘utf-8′));
Сергей Митрошин says:
Не сталкивался с этой проблемой. Возможно, следует указать utf-8 как кодировку по умолчанию в iconv.
17 февраля 2009, 8:28Artem says:
Сергей, а можно ли сделать средствами Zend_Fiter_Input валидацию с зависимостью на другие поля формы?
Например если у нас есть 3 поля даты (день, мес., год). Если все поля пустые, то всё впорядке, а если одно из полей введено, то нужно провалидировать введённое и все остальные поля (т.е. остальные поля становятся обязательными).
20 февраля 2009, 16:01Юрий Истомин says:
Если я хочу использовать встроенную проверку на обязательные поля, и при этом чтобы сообщения об ошибках были по-русски, придумался такой вариант:
21 февраля 2009, 6:02$filters = array();
$validators = array(
‘Автор’ => array(
Zend_Filter_Input::PRESENCE => Zend_Filter_Input::PRESENCE_REQUIRED,
Zend_Filter_Input::FIELDS => ‘author’,
),
);
$options = array(
Zend_Filter_Input::NOT_EMPTY_MESSAGE => ‘Поле “%rule%” обязательно для заполнения’,
);
$input = new Zend_Filter_Input($filters, $validators, $this->_request->getPost(), $options);
Сергей Митрошин says:
2 Артём:
К сожалению, не могу сказать. Видимо, копать надо в сторону своего валидатора, по аналогии с StringEquals:
$validators = array(
‘password’ => array(
‘StringEquals’,
‘fields’ => array(‘password1′, ‘password2′)
)
);
2 Юрий Истомин:
21 февраля 2009, 9:49Неплохой вариант, но сообщения надо выносить в конфиги. Хранить такие вещи в контроллерах – это хардкод.
Юрий Истомин says:
Согласен – конфиг или словарики, здесь я для примера захардкодил по-русски. Я ж предполагал просто передать имя поля, а валидатор чтобы сам перевел имя поля на русский язык и сформировал сообщение об ошибке. Кстати, я не нашел, где в Zend_Filter_Input прикручивается экземпляр Zend_Translate
21 февраля 2009, 13:03Сергей Митрошин says:
Надо в Zend_Registry положить с именем ‘Zend_Translate’. Валидаторы сами достанут его и будут использовать.
21 февраля 2009, 13:20Юрий Истомин says:
Как я подружил Zend_Filter_Input и Zend_Captcha.
$validators = array(
‘captcha’ => array(
$this->_getCaptcha(), // метод создает и настраивает класс капчи
Zend_Filter_Input::FIELDS => array(‘captcha’, ”),
),
);
Суть проблемы вот в чем: Zend_Captcha принимает от пользователя массив с ключами id – идентификатор капчи и input – введенное пользователем значение капчи.
23 февраля 2009, 3:48А вот Zend_Filter_Input, если ему передать массив, пытается провалидировать каждый элемент массива по очереди. То есть, Zend_Captcha::isValid() получает на вход сначала значение id, потом значение input – и два раза ругается “Empty captcha value”, поскольку ожидает на вход массив.
Но его можно обмануть. Если в настройке валидатора, в метакомманде ‘fields’, указать больше одной переменной для валидатора (как в примере проверки пароля с помощью StringEquals) – то Zend_Filter_Input передает значения валидатору как есть – массивом, не разбивая его по элементам. А если в массиве полей попадутся несуществующие, то Zend_Filter_Input их передавать валидатору не будет. Поэтому я и указал Zend_Filter_Input::FIELDS => array(‘captcha’, ”) – массив $_POST['captcha'] передастся как есть, а несуществующее поле $_POST[''] передаваться и не будет.
IgorN says:
Полезная статья
25 февраля 2009, 18:56юлий says:
столкнулся с проблемой валидации двух необязательных полей, с проверкой заполненности хотябы одного из них. проблема состоит в следующем – если поле не отмечено как required(true), то мой валидатор не срабатывает, т.е. в необязательном поле не хочет проверять оба поля, ниже кусок кода
…
public function isValid($value, $context = null) {
//cheсking if both fields are not empty
29 апреля 2009, 16:05if (strlen($context[$this->_field1]) == 0 && strlen($context[$this->_field2]) == 0){
$this->_messages[] = $this->_errorMessage;
return false;
}
…
Юрий Истомин says:
В ZF 1.9 немного поменялась валидация в Zend_Filter_Input – теперь проверка на пустое значение производится автоматически: если для правила указано Zend_Filter_Input::ALLOW_EMPTY => false, то Zend_Validate_NotEmpty добавляется в цепочку валидаторов, а если Zend_Filter_Input::ALLOW_EMPTY => true и проверка Zend_Validate_NotEmpty дает false (то есть поле пустое), валидация поля на этом заканчивается.
Проблема, собственно, в том, что для конкретного поля нельзя задать персональное сообщение о том, что поле надо заполнять – можно только указать общую для всех опцию Zend_Filter_Input::NOT_EMPTY_MESSAGE => ‘Поле “%rule%” обязательно для заполнения’. Для того, чтобы можно было задать более грамотное сообщение, я сделал дочерний класс:
class My_FilterInput extends Zend_Filter_Input
{
protected function _getNotEmptyMessage($rule, $field)
{
if (isset($this->_validatorRules[$rule][Zend_Filter_Input::NOT_EMPTY_MESSAGE])) {
return $this->_validatorRules[$rule][Zend_Filter_Input::NOT_EMPTY_MESSAGE];
} else {
return parent::_getNotEmptyMessage($rule, $field);
}
}
}
И теперь можно задать для конкретного правила конкретное сообщение:
‘comment’ => array(
26 августа 2009, 23:34Zend_Filter_Input::NOT_EMPTY_MESSAGE => ‘Введите текст комментария’,
Zend_Filter_Input::ALLOW_EMPTY => false,
),
‘email’ => array(
new Zend_Validate_EmailAddress(),
Zend_Filter_Input::MESSAGES => array(
array(Zend_Validate_EmailAddress::INVALID_FORMAT => ‘Введите корректный e-mail адрес’),
),
Zend_Filter_Input::ALLOW_EMPTY => false,
Zend_Filter_Input::NOT_EMPTY_MESSAGE => ‘Укажите e-mail’,
)
andrey says:
Добрый день. Можно подробнее про Zend_Filter_Input и Zend_Captcha.
У меня в html-файле(форма)
‘captcha’,
‘wordLen’ => 6,
‘timeout’ => 300,
));
$captcha->setFont(‘../library/Fonts/tahoma.ttf’);
$id = $captcha->generate();
?>
render($this);?>
Enter code *:
<input type="hidden" name="captcha[id]" value="”/>
в акшине
if($request = $this->getRequest()->isPost()) {
$captcha = new Zend_Captcha_Image(array(
‘name’ => ‘captcha-image’,
‘wordLen’ => 6,
‘timeout’ => 300,
));
$captcha->setFont(‘../library/Fonts/tahoma.ttf’);
$filters = array();
$validators = array(
// ‘name’ => array(
// ‘Alpha’, // Zend_Validate_Alpha
// array(‘StringLength’, 3, 20), // Zend_Validate_StringLength
// ‘presence’=>’required’ // обязательный параметр
// ),
// ‘phone’ => array(
// ‘Alpha’,
// array(‘stringLength’, 6, 15)
// ),
// ‘email’ => array(
// ‘EmailAddress’,
// ‘presence’=>’required’), //обязательный параметр
‘captcha’ => array(
$captcha, // метод создает и настраивает класс капчи
Zend_Filter_Input::FIELDS => array(‘captcha’,”))
);
$options = array(‘escapeFilter’ => ‘StringTrim’);
$input = new Zend_Filter_Input($filters, $validators, $_POST, $options);
if ($input->isValid()) {
$this->view->successMessages = “Thank you!”;
} else {
$this->view->errorMessages = $input->getMessages();
$this->view->params = $_POST;
}
}
Cообщение об ошибке Empty captcha value
4 декабря 2009, 15:15хотя выдаст
[captcha] => Array ( [id] => a7ff8d38f7542ebaba39f0887f7f1d07 [input] => fghfd
andrey says:
работает если поля имеют имя
<input type="hidden" name="id" value="”/>
а в фильтре
4 декабря 2009, 15:37Zend_Filter_Input::FIELDS => array(‘id’,'input’))
если поменять на другие – не работает
andrey says:
работает если поля имеют имя
а в фильтре
4 декабря 2009, 15:38Zend_Filter_Input::FIELDS => array(’id’,’input’))
если поменять на другие – не работает
andrey says:
что-то теги режутся
работает если поля имеют имя
а в фильтре
4 декабря 2009, 15:39Zend_Filter_Input::FIELDS => array(’id’,’input’))
если поменять на другие – не работает
andrey says:
короче id для id капчи и input для введённого значения
4 декабря 2009, 15:40Lyuba says:
Помогите мне пожалуйста!!!!!!!!!!! Мне нужно как-то поменять кодировку в zend studio for eclipse 6.1.0 а то у меня русские слова отображаются непонятными символами.
21 декабря 2009, 14:01