1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 21241 -->
4 <sect1 id="zend.validate.writing_validators">
6 <title>Escribiendo Validadores</title>
9 <classname>Zend_Validate</classname> provee un conjunto de validadores
10 que suelen necesitarse, pero inevitablemente, los desarrolladores quiere
11 escribir sus propios validadores personalizados para sus necesidades
12 particulares. La tarea de escribir un validador personalizado se
13 describe en esta sección. </para>
16 <classname>Zend_Validate_Interface</classname> define tres métodos,
17 isValid(), getMessages(), y getErrors(), que pueden ser implementadas
18 por clases de usuario a fin de crear objetos de validación
19 personalizados. Un objeto que implementa una interfaz
20 <classname>Zend_Validate_Interface</classname> puede añadirse a una
21 cadena de validación con
22 <methodname>Zend_Validate::addValidator()</methodname> . Tales
23 objetos también pueden ser usados con <link linkend="zend.filter.input">
24 <classname>Zend_Filter_Input</classname>
27 <para> De la descripción anterior de
28 <classname>Zend_Validate_Interface</classname> , podrá inferir que
29 las clases de validación que proporciona Zend Framework devuelven un
30 valor booleano para cuando un valor se valida satisfactoriamente o no.
31 También proporcionan información sobre <emphasis>por qué</emphasis> un
32 valor falló en la validación. La disponibilidad de las razones para los
33 fracasos de validación puede ser valiosa para una aplicación por
34 diversos motivos, tales como proporcionar estadísticas para análisis de
37 <para> La funcionalidad de los mensajes de validación básica de fallos están
38 implementados en <classname>Zend_Validate_Abstract</classname> . A fin
39 de incluir esta funcionalidad al crear una clase de validación,
40 simplemente extienda <classname>Zend_Validate_Abstract</classname> . En
41 la extensión de la clase deberá aplicar la lógica del método
42 <methodname>isValid()</methodname> y definir las variables y
43 plantillas de mensajes que correspondan a los tipos de fallos de
44 validación que puedan suceder. Si falla un valor en su test de
45 validación, entonces <methodname>isValid()</methodname> deberá devolver
46 <constant>FALSE</constant> . Si el valor pasa su test de validación,
47 entonces <methodname>isValid()</methodname> deberá devolver
48 <constant>TRUE</constant> . </para>
50 <para> En general, el método <methodname>isValid()</methodname> no debería
51 arrojar excepciones, salvo que sea imposible determinar si el valor de
52 entrada es válido o no. Algunos ejemplos de casos razonables para lanzar
53 una excepción podría ser si un archivo no puede abrirse, que un servidor
54 <acronym>LDAP</acronym> no pudiera ser contactado, o una conexión a
55 una base de datos no estuviera disponible. Estos son casos en los que
56 puede ser necesario determinar el éxito o fracaso de la validación. </para>
58 <example id="zend.validate.writing_validators.example.simple">
60 <title>Crear una Clase de Validación sencilla</title>
62 <para> El siguiente ejemplo demuestra cómo podría escribirse un sencillo
63 validador personalizado. En este caso las reglas de validación son
64 simplemente que el valor de entrada debe ser de punto flotante. <programlisting language="php"><![CDATA[
65 class MyValid_Float extends Zend_Validate_Abstract
67 const FLOAT = 'float';
69 protected $_messageTemplates = array(
70 self::FLOAT => "'%value%' no es un valor de punto flotante"
73 public function isValid($value)
75 $this->_setValue($value);
77 if (!is_float($value)) {
85 ]]></programlisting> La clase define una plantilla para su único mensaje de
86 fallo de validación, que incluye el mágico parámetro
87 <emphasis>%value%</emphasis> . La llamada a
88 <methodname>_setValue()</methodname> prepara al objeto para
89 insertar automáticamente en el mensaje de fallo al valor probado, si
90 éste falla en la validación. La llamada a
91 <methodname>_error()</methodname> sigue las pistas para
92 establecer una razón por el fracaso de la validación. Dado que esta
93 clase sólo define un mensaje de fallo, no es necesario darle a
94 <methodname>_error()</methodname> el nombre de la plantilla del
95 mensaje de fallo. </para>
99 <example id="zend.validate.writing_validators.example.conditions.dependent">
101 <title>Escribiendo una Clase de Validación habiendo Condiciones
102 Dependientes </title>
103 <para> El siguiente ejemplo muestra un conjunto de reglas de validación
104 más complejo, donde es necesario que el valor de entrada ser
105 numérico y dentro del límite de un rango de valores mínimos y
106 máximos. Un valor de entrada podría fallar en la validación
107 exactamente por una de las siguientes razones: </para>
111 <para>El valor de entrada no es numérico.</para>
114 <para>El valor de entrada es menor que el valor mínimo
118 <para>El valor de entrada es mayor que el valor máximo
123 <para> Estas razones en el fallo de validación, son traducidas a las
124 definiciones en la clase: </para>
126 <programlisting language="php"><![CDATA[
127 class MyValid_NumericBetween extends Zend_Validate_Abstract
129 const MSG_NUMERIC = 'msgNumeric';
130 const MSG_MINIMUM = 'msgMinimum';
131 const MSG_MAXIMUM = 'msgMaximum';
134 public $maximum = 100;
136 protected $_messageVariables = array(
141 protected $_messageTemplates = array(
142 self::MSG_NUMERIC => "'%value%' no es numérico",
143 self::MSG_MINIMUM => "'%value%' debe ser al menos '%min%'",
144 self::MSG_MAXIMUM => "'%value%' debe ser no mayor a '%max%'"
147 public function isValid($value)
149 $this->_setValue($value);
151 if (!is_numeric($value)) {
152 $this->_error(self::MSG_NUMERIC);
156 if ($value < $this->minimum) {
157 $this->_error(self::MSG_MINIMUM);
161 if ($value > $this->maximum) {
162 $this->_error(self::MSG_MAXIMUM);
171 <para> Las propiedades públicas <varname>$minimum</varname> y
172 <varname>$maximum</varname> se han establecido para proporcionar
173 los límites mínimo y máximo, respectivamente, de un valor a validar.
174 La clase también define dos variables de mensajes que corresponden a
175 las propiedades públicas y permiten usar <property>min</property> y
176 <property>max</property> en plantillas de mensajes como
177 parámetros mágicos, al igual que con <property> value </property> . </para>
179 <para> Tenga en cuenta que si cualquiera de las comprobaciones de
180 validación falla en <methodname>isValid()</methodname> , ya está
181 preparado un mensaje apropiado, y el método inmediatamente devuelve
182 <constant>FALSE</constant> . Estas reglas de validación son por
183 lo tanto secuencialmente dependientes. Es decir, si uno de los tests
184 falla, no hay necesidad de poner a prueba las posteriores reglas de
185 validación. Sin embargo, esta necesidad no será el caso. El
186 siguiente ejemplo ilustra cómo escribir una clase con reglas de
187 validación independientes, donde el objeto validación puede devolver
188 múltiples razones por las cuales fracasó un intento de validación en
194 id="zend.validate.writing_validators.example.conditions.independent">
196 <title>Validación con Condiciones Independientes, Múltiples Razones del
198 <para> Considere escribir una clase de validación y control de
199 contraseñas - cuando es necesario que un usuario elija una
200 contraseña que cumple determinados criterios para ayudar a tener
201 cuentas de usuario seguras. Supongamos que la seguridad de la
202 contraseña aplica criterios que fuerzan a lo siguiente: </para>
206 <para>debe tener al menos una longitud de 8 caracteres,</para>
209 <para>contener al menos una letra en mayúscula,</para>
212 <para>contener al menos una letra en minúscula,</para>
215 <para>contener al menos un dígito.</para>
219 <para> La siguiente clase implementa estos criterios de validación: <programlisting language="php"><![CDATA[
220 class MyValid_PasswordStrength extends Zend_Validate_Abstract
222 const LENGTH = 'length';
223 const UPPER = 'upper';
224 const LOWER = 'lower';
225 const DIGIT = 'digit';
227 protected $_messageTemplates = array(
228 self::LENGTH => "'%value%' debe tener al menos una longitud de 8 caracteres",
229 self::UPPER => "'%value%' debe contener al menos una letra en mayúscula",
230 self::LOWER => "'%value%' debe contener al menos una letra en minúscula",
231 self::DIGIT => "'%value%' debe contener al menos un dígito"
234 public function isValid($value)
236 $this->_setValue($value);
240 if (strlen($value) < 8) {
241 $this->_error(self::LENGTH);
245 if (!preg_match('/[A-Z]/', $value)) {
246 $this->_error(self::UPPER);
250 if (!preg_match('/[a-z]/', $value)) {
251 $this->_error(self::LOWER);
255 if (!preg_match('/\d/', $value)) {
256 $this->_error(self::DIGIT);
263 ]]></programlisting> Las cuatro pruebas de criterio en
264 <methodname>isValid()</methodname> no devuelven inmediatamente
265 <constant>FALSE</constant> . Esto permite a la clase de
266 validación a proporcionar <emphasis role="bold">todas</emphasis> las
267 razones por las que la contraseña de entrada no cumplió los
268 requisitos de validación. Si, por ejemplo, un usuario ingresara el
269 string " <methodname>#$%</methodname> " como contraseña,
270 <methodname>isValid()</methodname> causaría que los cuatro
271 mensajes de fracaso de validación sean devueltos por un llamado
272 posterior a <methodname>getMessages()</methodname> . </para>