1 <sect1 id="zend.validate.writing_validators">
3 <title>Pisanie weryfikatorów</title>
6 Zend_Validate zapewnia zestaw najczęściej potrzebnych weryfikatorów, ale
7 programiści często potrzebują napisać własne weryfikatory dla ich
8 szczególnych zastosowań. Zadanie pisania własnego filtru jest opisane w
13 Interfejs <code>Zend_Validate_Interface</code> definiuje trzy metody,
14 <code>isValid()</code>, <code>getMessages()</code> oraz
15 <code>getErrors()</code>, które mogą być zaimplementowane przez klasę
16 użytkownika w celu utworzenia własnych obiektów weryfikujących. Obiekt,
17 który implementuje interfejs <code>Zend_Validate_Interface</code>
18 może być dodany do łańcucha weryfikatorów za pomocą metody
19 <code>Zend_Validate::addValidator()</code>.
20 Taki obiekt może być także użyty przez klasę
21 <link linkend="zend.filter.input"><code>Zend_Filter_Input</code></link>.
25 As you may already have inferred from the above description of <code>Zend_Validate_Interface</code>,
26 validation classes provided with Zend Framework return a boolean value for whether or not a value validates
27 successfully. They also provide information about <emphasis role="bold">why</emphasis> a value failed
28 validation. The availability of the reasons for validation failures may be valuable to an application for
29 various purposes, such as providing statistics for usability analysis.
33 Basic validation failure message functionality is implemented in <code>Zend_Validate_Abstract</code>. To
34 include this functionality when creating a validation class, simply extend
35 <code>Zend_Validate_Abstract</code>. In the extending class you would implement the
36 <code>isValid()</code> method logic and define the message variables and message templates that correspond to
37 the types of validation failures that can occur. If a value fails your validation tests, then
38 <code>isValid()</code> should return <code>false</code>. If the value passes your validation tests, then
39 <code>isValid()</code> should return <code>true</code>.
43 In general, the <code>isValid()</code> method should not throw any exceptions, except where it is impossible
44 to determine whether or not the input value is valid. A few examples of reasonable cases for throwing an
45 exception might be if a file cannot be opened, an LDAP server could not be contacted, or a database
46 connection is unavailable, where such a thing may be required for validation success or failure to be
50 <example id="zend.validate.writing_validators.example.simple">
52 <title>Creating a Simple Validation Class</title>
55 The following example demonstrates how a very simple custom validator might be written. In this case the
56 validation rules are simply that the input value must be a floating point value.
58 <programlisting role="php"><![CDATA[
59 class MyValid_Float extends Zend_Validate_Abstract
61 const FLOAT = 'float';
63 protected $_messageTemplates = array(
64 self::FLOAT => "'%value%' is not a floating point value"
67 public function isValid($value)
69 $this->_setValue($value);
71 if (!is_float($value)) {
82 The class defines a template for its single validation failure message, which includes the built-in magic
83 parameter, <code>%value%</code>. The call to <code>_setValue()</code> prepares the object to insert the
84 tested value into the failure message automatically, should the value fail validation. The call to
85 <code>_error()</code> tracks a reason for validation failure. Since this class only defines one failure
86 message, it is not necessary to provide <code>_error()</code> with the name of the failure message
92 <example id="zend.validate.writing_validators.example.conditions.dependent">
94 <title>Writing a Validation Class having Dependent Conditions</title>
97 The following example demonstrates a more complex set of validation rules, where it is required that the
98 input value be numeric and within the range of minimum and maximum boundary values. An input value would
99 fail validation for exactly one of the following reasons:
103 <para>The input value is not numeric.</para>
106 <para>The input value is less than the minimum allowed value.</para>
109 <para>The input value is more than the maximum allowed value.</para>
115 These validation failure reasons are then translated to definitions in the class:
117 <programlisting role="php"><![CDATA[
118 class MyValid_NumericBetween extends Zend_Validate_Abstract
120 const MSG_NUMERIC = 'msgNumeric';
121 const MSG_MINIMUM = 'msgMinimum';
122 const MSG_MAXIMUM = 'msgMaximum';
125 public $maximum = 100;
127 protected $_messageVariables = array(
132 protected $_messageTemplates = array(
133 self::MSG_NUMERIC => "'%value%' is not numeric",
134 self::MSG_MINIMUM => "'%value%' must be at least '%min%'",
135 self::MSG_MAXIMUM => "'%value%' must be no more than '%max%'"
138 public function isValid($value)
140 $this->_setValue($value);
142 if (!is_numeric($value)) {
143 $this->_error(self::MSG_NUMERIC);
147 if ($value < $this->minimum) {
148 $this->_error(self::MSG_MINIMUM);
152 if ($value > $this->maximum) {
153 $this->_error(self::MSG_MAXIMUM);
163 The public properties <code>$minimum</code> and <code>$maximum</code> have been established to provide
164 the minimum and maximum boundaries, respectively, for a value to successfully validate. The class also
165 defines two message variables that correspond to the public properties and allow <code>min</code> and
166 <code>max</code> to be used in message templates as magic parameters, just as with <code>value</code>.
170 Note that if any one of the validation checks in <code>isValid()</code> fails, an appropriate failure
171 message is prepared, and the method immediately returns <code>false</code>. These validation rules are
172 therefore sequentially dependent. That is, if one test should fail, there is no need to test any
173 subsequent validation rules. This need not be the case, however. The following example illustrates how to
174 write a class having independent validation rules, where the validation object may return multiple
175 reasons why a particular validation attempt failed.
180 <example id="zend.validate.writing_validators.example.conditions.independent">
182 <title>Validation with Independent Conditions, Multiple Reasons for Failure</title>
185 Consider writing a validation class for password strength enforcement - when a user is required to choose
186 a password that meets certain criteria for helping secure user accounts. Let us assume that the password
187 security criteria enforce that the password:
191 <para>is at least 8 characters in length,</para>
194 <para>contains at least one uppercase letter,</para>
197 <para>contains at least one lowercase letter,</para>
200 <para>and contains at least one digit character.</para>
206 The following class implements these validation criteria:
208 <programlisting role="php"><![CDATA[
209 class MyValid_PasswordStrength extends Zend_Validate_Abstract
211 const LENGTH = 'length';
212 const UPPER = 'upper';
213 const LOWER = 'lower';
214 const DIGIT = 'digit';
216 protected $_messageTemplates = array(
217 self::LENGTH => "'%value%' must be at least 8 characters in length",
218 self::UPPER => "'%value%' must contain at least one uppercase letter",
219 self::LOWER => "'%value%' must contain at least one lowercase letter",
220 self::DIGIT => "'%value%' must contain at least one digit character"
223 public function isValid($value)
225 $this->_setValue($value);
229 if (strlen($value) < 8) {
230 $this->_error(self::LENGTH);
234 if (!preg_match('/[A-Z]/', $value)) {
235 $this->_error(self::UPPER);
239 if (!preg_match('/[a-z]/', $value)) {
240 $this->_error(self::LOWER);
244 if (!preg_match('/\d/', $value)) {
245 $this->_error(self::DIGIT);
255 Note that the four criteria tests in <code>isValid()</code> do not immediately return <code>false</code>.
256 This allows the validation class to provide <emphasis role="bold">all</emphasis> of the reasons that the
257 input password failed to meet the validation requirements. If, for example, a user were to input the
258 string "<code>#$%</code>" as a password, <code>isValid()</code> would cause all four validation failure
259 messages to be returned by a subsequent call to <code>getMessages()</code>.