Zend_Validate-WritingValidators.xml 11 KB

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