Validando formulários com Zend Form, jQuery e Ajax.

Sabemos que validar formulários hoje em dia é uma obrigação de todo bom desenvolvedor. E não validar apenas no cliente usando javascript, mas validar também no servidor. Validação é o primeiro de muitos passos para tornar sua aplicação mais segura.

Uma técnica que eu acabei descobrindo recentemente e estou usando bastante é juntar o poder do componente Zend_Form com o beleza do jQuery, o que me trouxe resultados muito bons, principalmente nos quesitos qualidade e desenvolvimento ágil.

Para demostrar essa técnica que eu estou utilizando eu vou partir do pressuposto que você já esta familiarizado com o ambiente do Zend Framework. Partindo disso, vou mostrar o código simples do formulário de cadastro:

<?php

class Cadastro_Form extends Zend_Form {
        public function init() {
                $this->setAttrib(‘id’, ‘cadastro’)
                     ->setAction(‘/index/index’)
                     ->setMethod(‘post’);
                $this->addElement( ‘text’, ‘nome’, array(
                        ‘label’                 => ‘Nome’,
                        ‘required’              => true,
                        ‘validators’    => array(
                                ‘NotEmpty’,
                                array(‘StringLength’, false, array(0, 60) )
                        )
                ));
                $this->addElement(‘text’, ‘email’, array(
                    ‘label’         => ‘E-mail’,
                    ‘required’      => true,
                    ‘validators’   => array(
                        ‘NotEmpty’,
                        ‘EmailAddress’
                    )
                ));
                $this->addElement( ‘submit’, ‘submit’, array(
                        ‘ignore’        => true,
                        ‘label’         => ‘Entrar’
                ));
                $this->getElement(‘submit’)->removeDecorator(‘label’);
        }
}

Agora que nosso formulário de cadastro já é um componente do projeto, vamos fazer as paginas, vou supor aqui que estamos trabalhando no controller index, portando criaremos duas actions para que nosso controller aqui fique da seguinte maneira:

class IndexController extends Zend_Controller_Action {
        /** Nesta action iremos exibir o formulario */
        public function indexAction() {}
        /** Nesta action iremos receber o dados por ajax para validação */
        public function validarAction() {}
}

Temos o básico para começarmos a trabalhar. Agora a ideia é validarmos estes dados na tela do cliente via ajax, para que antes do cliente submeter os dados ele consiga visualizar os possíveis erros e já corrigi-los. Lembrando também que isso NÃO descarta a validação no servidor.

Vamos ver como fica nosso metodo indexAction():

public function indexAction() {
        $form = new Cadastro_Form;
        if ($this->_request->isPost()) {
                if ($form->isValid( $this->_request->getPost() )) {
                        $this->view->mensagem = ‘Formulario valido’;
                }
                else {
                        $this->view->mensagem = ‘Ops. Formulario invalido.’;
                        $form->populate( $this->_request->getPost() );
                }
        }
        $this->view->form = $form;
}

E agora nossa index.phtml

<?php if (isset($this->mensagem)) { ?>
<p><?php echo $this->mensagem; ?></p>
<?php echo $this->form; ?>

Não podemos esquecer de adicionar a biblioteca jQuery a nossa camada view, pois ela irá nos ajudar muito no processo, vejamos o nosso código javascript para a validação:

$(document).ready(function() {
        $(‘#submit’).bind(‘click’, function (e) {
                e.preventDefault();
                var nome = $(‘#nome’).val();
                var email = $(‘#email’).val();
                $.ajax({
                        url: ‘/index/validar’,
                        type: ‘post’,
                        dataType: ‘json’,
                        data: {
                                nome: nome,
                                email: email
                        }
                        success: function (data) {
                                $(‘.form-errors’).remove();
                                if (data == true) alert( ‘Passou…’ );
                                else {
                                        for (campo in data) {
                                                $(‘#’+campo).after(‘<ul id="’+campo+‘_errors" class="form-errors"></ul>’);
                                                for (mensagem in data[campo]) {
                                                        $(‘#’+campo+‘_errors’).append(‘<li>’+data[campo][mensagem]+‘</li>’);
                                                }
                                        }
                                }
                        }
                });
        });
});

Como vocês podem ver, nosso método validar irá retornar um objeto json para o jQuery poder trabalhar, e com o for iremos percorrer este objeto colocando cada mensagem em seu devido lugar. É um bom método por não fazer você ter que escrever duas validações, uma para javascript e outra para php. Você escreve apenas uma e utiliza em ambas as validações.

Agora nosso método validar:

public function validarAction() {
        if ($this->_request->isXmlHttpRequest()) {
                $form = new Cadastro_Form;
                echo $form->processAjax($this->_request->getPost());
        }
}

Como vocês viram, devido ao nosso componente de formulário já está pronto tudo ficou muito mais simples, com apenas algumas linhas validamos e retornamos o resultado para o javascript poder exibir ao usuário.

O resultado desta combinação é muito interessante, pois mantem nossa aplicação modularizada, de forma que para adicionar novos campos no nosso formulário de cadastro não é necessário se preocupar com html e validação javascript, basta editar o componente Cadastro_Form.

Qualquer duvida deixa nos comentários ai que vamos trocando uma ideia. :)

Referencias:

http://framework.zend.com/manual/en/zend.form.html

http://framework.zend.com/manual/en/zend.validate.html

http://docs.jquery.com/Ajax

Comments (7)

Fabio Milheirojulho 21st, 2009 at 14:33

Excelente artigo! Tudo a funcionar excepto um pormenor.. O captcha.

O meu captcha tem id “captcha”, mas a textbox com o valor inserido pelo utilizador para verificar que este é humano tem um id “captcha-input” que é gerado automaticamente a partir do id original “captcha”.

O problema é que o JavaScript não aceita que eu escreva:
captcha-input: captcha-input,
no parametro data. Parece que entende aquilo como uma subtração.

Tentei fazer o seguinte:

var captcha_input = $(‘#captcha-input’).val(); // O javascript só aceita underscore…

e no parâmetro data usei
captcha_input: captcha_input,

Se criar um alert no ciclo que escreve as mensagens de erro, o campo captcha não é mencionado.

O que está a correr mal??

Obrigado

PS: Sem usar AJAX, o form funciona perfeitamente.

Fabio Milheiroagosto 24th, 2009 at 10:32

Como podemos personalizar as mensagens de erro?

Diego Henriqueagosto 24th, 2009 at 10:56

Oi Fabio,

Vou preparar um post sobre como traduzir e personalizar as mensagens de erro do Zend_Validate.

Abraços

Fabio Milheiroagosto 24th, 2009 at 14:26

Obrigado! Deixe-me só adiantar que arranjei uma maneira de fazer isso no Bootstrap, mas quando activo essas traduções/customizações, a validação apresenta mensagens com o texto “null” em vez das mensagens traduzidas ou as originais…

protected function _initFormMessages()
{
$translateValidators = array(
Zend_Validate_NotEmpty::IS_EMPTY => ‘Campo obrigatório’,
Zend_Validate_Regex::NOT_MATCH => ‘Valor inválido’,
Zend_Validate_Date::NOT_YYYY_MM_DD => ‘Formato inválido (YYYY-MM-DD)’,
Zend_Validate_StringLength::TOO_SHORT => ‘Campo não pode ter menos do que %min% caracteres’,
Zend_Validate_StringLength::TOO_LONG => ‘Campo não pode ter mais do que %max% caracteres’,
Zend_Validate_EmailAddress::INVALID => ‘Endereço de e-mail inválido’,
Zend_Validate_Digits::NOT_DIGITS => ‘Campo só pode conter algarismos’
);
$translator = new Zend_Translate(‘array’, $translateValidators);
Zend_Validate_Abstract::setDefaultTranslator($translator);
}

Isto funciona bem sem a validação ajax. Na validação ajax, as mensagens de erro passam a aparecer “null” (todas elas).

Vou ficar a aguardar o seu post. Mais uma vez obrigado! Abraços

Diego Henriqueagosto 24th, 2009 at 14:34

Fabio,

Talvez seja melhor você definir as mensagens diretamente no seu formulário. ;)
Inclusive, vou preparar um post mostrando essa ideia.

Abraços

Maxwellabril 6th, 2010 at 12:26

Cara, tu tem um exemplo prático desse formulario para o zend 1.10??
eu to tentando aprender, pelo site la é complicado, e pela internet é só de versões antigas, e outra, eu só aprendo vendo a na prática, pois eu me perco na hora d colocar os códigos nos lugares certos, com os nomes certos.

Felipe Duardomaio 3rd, 2010 at 08:51

não sei se estou fazendo algo errado… mas quando eu clico no submit aparece aquele alert de passou mesmo não preenchendo nada nos campos…

to quebrando a cabeça pra fazer pois meio iniciante no zend

Leave a comment

Your comment