Zend_Validate-WritingValidators.xml 12 KB

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