Validación encadenada de formularios usando Zend_Filter_Input

Zend_Validator junto con Zend_Filter se convierten en una herramienta bastante poderosa para la validación de datos y formularios.
Hay que tener en cuenta que gracias a la arquitectura de Libre Uso (Use At Will) de Zend Framework, este pedazo de código puede ser usado en cualquier proyecto sin importar si se implementa MVC o no.

Como ejemplos anteriores, este es bastante sencillo:

El indexAction() muestra la vista con el formulario que debe ser validado, si no se usa MVC olvidémoslo.

validateAction() es donde todo sucede, primero se declara una clase con un validador personalizado (que explicaré luego). La validación encadenada es creada, cada una especifica la clase de validación que se utiliza con sus respectivos parámetros y los mensajes predeterminados a mostrar.

Los mensajes personalizados son una característica bastante útil, especialmente cuando se desarrollan aplicaciones multi-lenguaje.

Luego se crea un array con los filtros a aplicar, no todos los datos son filtrados. En este caso, solo la edad, la dirección y el número telefónico son “limpiados” para evitar que lleguen caracteres prohibidos.

Finalmente Zend_Filter_Input entra en el juego, recibiendo todos los datos del formulario y chequeando todos en un solo llamado al método isValid().

Adicionalmente, estoy usando FlashMessenger para almacenar los mensajes de éxito o error y mostrarlos en el próximo llamado HTTP. Recuerde que los mensajes del FlashMessenger no pueden ser mostrados en la misma acción que se instancian.

Cualquier duda o comentario en [email protected][ElCorreodeGoogle].com

class ValidatorController extends Zend_Controller_Action
{
    /**
     * Renders the form
     *
     */
    public function indexAction()
    {
        show_source(PATH_CONTROLLERS . 'ExampleController.php');
    }

    /**
     * Validates the input
     *
     */
    public function validateAction()
    {
        /**
         * The included class is an example of custom validators
         */
        require_once PATH_CLASSES . 'My_Validate_Url.php';
        $validurl = new My_Validate_Url();
        $validurl->setMessage('Invalid URL', My_Validate_URL::NOT_MATCH);
        $validurl->setMessage('Empty', My_Validate_URL::STRING_EMPTY);
        $validators = array(
             'address' => array('Alnum', new Zend_Validate_Alnum(true),
                                'messages' => array(
                                'Address not valid', // Default error message
                                // Specific error messages
                                array(Zend_Validate_Alnum::NOT_ALNUM =>
                                      'Address contains invalid characters',
                                      Zend_Validate_Alnum::STRING_EMPTY =>
                                      'Address field is mandatory'))),
             'phone'   => array('Digits', new Zend_Validate_Digits(),
                                'messages' => array(
                                'Wrong phone number format',
                                array(Zend_Validate_Digits::NOT_DIGITS =>
                                      'Phone number can only have digits',
                                      Zend_Validate_Digits::STRING_EMPTY =>
                                      'Phone number can not be empty'))),
             'age'     => array('Digits', new Zend_Validate_Between(16, 59),
                                'messages' => array(
                                'You do not qualify because of your age',
                                array(Zend_Validate_Between::NOT_BETWEEN => 
                                      'Age is not between the allowed range'))),
             'id'      => array('StringLength', new Zend_Validate_StringLength(8, 10),
                                'messages' => array(
                                'ID not valid',
                                array(Zend_Validate_StringLength::TOO_LONG =>
                                      'ID is too long',
                                      Zend_Validate_StringLength::TOO_SHORT =>
                                      'ID is too short'))),
             'date'    => array('Date', new Zend_Validate_Date(),
                                'messages' => array(
                                'Wrong date',
                                array(Zend_Validate_Date::INVALID =>
                                      'Date not recognized as valid',
                                      Zend_Validate_Date::FALSEFORMAT =>
                                      'Date format is incorrect',
                                      Zend_Validate_Date::NOT_YYYY_MM_DD =>
                                     'Date format must be YYYY-MM-DD'))),
              'url'      => $validurl
           );


        /**
         * Age, address and phone are also filtered
         * The true param in Zend_Filter_Alnum tells it to allows whitespaces
         */
        $filters = array('age'      => 'Int',
                         'address'  => array('Alnum', new Zend_Filter_Alnum(true)),
                         'phone'    => 'Digits');

        // Now we chain the validators, the filters and pass the post params on
        $input = new Zend_Filter_Input($filters, $validators);
        $input->setData($this->getRequest()->getParams());

        // Check whether errors occur
        if ($input->isValid())
        {
            $this->_helper->FlashMessenger->addMessage('Success!');
            $this->_helper->redirector('index');
        } else {
            $messages = $input->getMessages();
            foreach ($messages as $key => $value)
            {
                // Store all messages in FlashMessenger
                foreach ($value as $msg)
                {
                    $this->_helper->FlashMessenger->addMessage($msg);
                }
            }
        }

        // There are errors, the index action will show them...
        $this->_helper->redirector('index');
    }
}