| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.validate.writing_validators">
- <title>Написание валидаторов</title>
- <para>
- <classname>Zend_Validate</classname> предоставляет набор наиболее
- часто используемых валидаторов, но разработчики часто сталкиваются
- с такими ситуациями, когда требуется написание своих валидаторов.
- В этом разделе описан процесс написания своих валидаторов.
- </para>
- <para>
- <classname>Zend_Validate_Interface</classname> определяет три метода:
- <code>isValid()</code>, <code>getMessages()</code> и
- <code>getErrors()</code>, они должны
- реализовываться в ваших классах валидации.
- Объект, реализующий данный интерфейс, может быть добавлен в цепочку
- валидаторов через метод <code>Zend_Validate::addValidator()</code>,
- также такие объекты могут использоваться с классом
- <link linkend="zend.filter.input"><classname>Zend_Filter_Input</classname></link>.
- </para>
- <para>
- Как вы наверное уже поняли из приведенного выше описания
- интерфейса <classname>Zend_Validate_Interface</classname>,
- классы валидации, предоставляемые Zend Framework, возвращают
- булево значение, означающее успех/неуспех валидации.
- Они также предоставляют информацию о том
- <emphasis>почему</emphasis> переданное значение не прошло
- валидацию. Возможность узнать причину того, почему значение не проходит
- валидацию, может быть полезна для различных целей, как, например,
- создание статистики для анализа удобства использования приложения.
- </para>
- <para>
- Базовый функционал для сообщений об ошибке валидации реализован в
- классе <classname>Zend_Validate_Abstract</classname>.
- Для того, чтобы использовать этот функционал при создании класса
- валидации, просто наследуйте свой класс от
- <classname>Zend_Validate_Abstract</classname>.
- В классе-наследнике вы можете реализовать логику метода
- <code>isValid()</code>, а также определить шаблоны и переменные
- сообщений, которые соответствуют различным типам ошибок валидации.
- Если значение не проходит проверку, то <code>isValid()</code> должен
- возвращать <constant>FALSE</constant>. Если значение проходит проверку, то
- <code>isValid()</code> должен возвращать <constant>TRUE</constant>.
- </para>
- <para>
- Обычно метод <code>isValid()</code> не должен бросать никаких
- исключений, за исключением тех ситуаций, когда невозможно определить,
- является ли валидным входное значение или нет.
- Например, бросок исключения уместен в случае,
- когда невозможно открыть файл (недоступен сервер LDAP,
- нет соединения с базой данных), и процесс валидации не может быть
- продолжен.
- </para>
- <example id="zend.validate.writing_validators.example.simple">
- <title>Создание простого класса валидации</title>
- <para>
- Следующий пример демонстрирует создание простейшего валидатора.
- В данном случае правила валидации просты - входное значение
- должно иметь тип <code>float</code>.
- <programlisting language="php"><![CDATA[
- class MyValid_Float extends Zend_Validate_Abstract
- {
- const FLOAT = 'float';
- protected $_messageTemplates = array(
- self::FLOAT => "'%value%' не является числом с плавающей точкой"
- );
- public function isValid($value)
- {
- $this->_setValue($value);
- if (!is_float($value)) {
- $this->_error();
- return false;
- }
- return true;
- }
- }
- ]]></programlisting>
- В данном классе определен шаблон для единственного сообщения
- об ошибке валидации, который включает в себя встроенный "магический"
- параметр <code>%value%</code>.
- Вызов <code>_setValue()</code> подготавливает объект к подстановке
- проверяемого значения в сообщение об ошибке.
- Вызов <code>_error()</code> устанавливает причину ошибки валидации.
- Поскольку в этом классе только одно сообщение об ошибке,
- то нет необходимости передавать методу <code>_error()</code>
- имя шаблона сообщения об ошибке.
- </para>
- </example>
- <example id="zend.validate.writing_validators.example.conditions.dependent">
- <title>Написание классов валидации с подчиненными условиями</title>
- <para>
- Следующий пример демонстрирует более сложный набор правил валидации,
- где требуется, чтобы входное значение было числом, находящимся
- в диапазоне между минимальным и максимальным значениями.
- Значение может не пройти валидацию по одной из следующих причин:
- <itemizedlist>
- <listitem>
- <para>Значение не является числом.</para>
- </listitem>
- <listitem>
- <para>Значение меньше минимально допустимого.</para>
- </listitem>
- <listitem>
- <para>Значение больше максимально допустимого.</para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Эти возможные причины переводятся в определения в классе:
- <programlisting language="php"><![CDATA[
- class MyValid_NumericBetween extends Zend_Validate_Abstract
- {
- const MSG_NUMERIC = 'msgNumeric';
- const MSG_MINIMUM = 'msgMinimum';
- const MSG_MAXIMUM = 'msgMaximum';
- public $minimum = 0;
- public $maximum = 100;
- protected $_messageVariables = array(
- 'min' => 'minimum',
- 'max' => 'maximum'
- );
- protected $_messageTemplates = array(
- self::MSG_NUMERIC => "'%value%' не является числом",
- self::MSG_MINIMUM => "'%value%' должен быть не меньше '%min%'",
- self::MSG_MAXIMUM => "'%value%' должен быть не больше '%max%'"
- );
- public function isValid($value)
- {
- $this->_setValue($value);
- if (!is_numeric($value)) {
- $this->_error(self::MSG_NUMERIC);
- return false;
- }
- if ($value < $this->minimum) {
- $this->_error(self::MSG_MINIMUM);
- return false;
- }
- if ($value > $this->maximum) {
- $this->_error(self::MSG_MAXIMUM);
- return false;
- }
- return true;
- }
- }
- ]]></programlisting>
- Открытые свойства <varname>$minimum</varname> и <varname>$maximum</varname>
- были созданы для установки нижней и верхней границ диапазона
- соответственно.
- В классе также определены две переменные сообщений, которые
- соответствуют этим открытым свойствам и позволяют использовать
- <code>min</code> и <code>max</code>
- в качестве магических параметров в шаблонах сообщений, так же,
- как и <code>value</code>.
- </para>
- <para>
- Обратите вмимание, что если какая-либо из проверок в методе
- <code>isValid()</code> не была пройдена, то подготавливается
- соответствующее сообщение и метод сразу же возвращает
- <constant>FALSE</constant>.
- Таким образом, эти правила валидации являются
- последовательно-зависимыми. Это значит, что если одна из проверок не
- была пройден, то нет необходимости производить последующие проверки.
- Но это не обязательный случай, в следующем примере показан
- класс с независимыми правилами валидации, где объект
- валидации может возвращать несколько причин, по которым валидация
- не была пройдена.
- </para>
- </example>
- <example id="zend.validate.writing_validators.example.conditions.independent">
- <title>Валидация с независимыми условиями и возвратом нескольких причин непрохождения валидации</title>
- <para>
- Рассмотрим написание класса валидации для обеспечения стойкости
- пароля, где от пользователя требуется
- выбрать пароль, который соответствует определенным критериям в целях
- защиты пользовательского аккаунта.
- Предположим, что критерии безопасности требуют, чтобы пароль:
- <itemizedlist>
- <listitem>
- <para>был длиной как минимум 8 символов,</para>
- </listitem>
- <listitem>
- <para>содержал как минимум одну букву в верхнем регистре,</para>
- </listitem>
- <listitem>
- <para>содержал как минимум одну букву в нижнем регистре,</para>
- </listitem>
- <listitem>
- <para>содержал как минимум один цифровой символ.</para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Следующий класс реализует эти критерии валидации:
- <programlisting language="php"><![CDATA[
- class MyValid_PasswordStrength extends Zend_Validate_Abstract
- {
- const LENGTH = 'length';
- const UPPER = 'upper';
- const LOWER = 'lower';
- const DIGIT = 'digit';
- protected $_messageTemplates = array(
- self::LENGTH => "'%value%' должен быть длиной как минимум 8 символов",
- self::UPPER => "'%value%' должен содержать как минимум одну букву в верхнем регистре",
- self::LOWER => "'%value%' должен содержать как минимум одну букву в нижнем регистре",
- self::DIGIT => "'%value%' должен содержать как минимум один цифровой символ"
- );
- public function isValid($value)
- {
- $this->_setValue($value);
- $isValid = true;
- if (strlen($value) < 8) {
- $this->_error(self::LENGTH);
- $isValid = false;
- }
- if (!preg_match('/[A-Z]/', $value)) {
- $this->_error(self::UPPER);
- $isValid = false;
- }
- if (!preg_match('/[a-z]/', $value)) {
- $this->_error(self::LOWER);
- $isValid = false;
- }
- if (!preg_match('/\d/', $value)) {
- $this->_error(self::DIGIT);
- $isValid = false;
- }
- return $isValid;
- }
- }
- ]]></programlisting>
- Обратите внимание, что эти четыре проверки в методе
- <code>isValid()</code> не сразу же возвращают <constant>FALSE</constant>.
- Это позволяет классу валидации предоставлять
- <emphasis>все</emphasis> причины того, почему
- введенный пароль не отвечает требованиям валидации.
- Если, например, пользователь введет строку "<code>#$%</code>"
- в качестве пароля, то после <code>isValid()</code>
- вызов <code>getMessages()</code> вернет все четыре
- сообщения ошибки валидации.
- </para>
- </example>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|