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:
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:
/** 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():
$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
<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:
$(‘#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:
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
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.
Como podemos personalizar as mensagens de erro?
Oi Fabio,
Vou preparar um post sobre como traduzir e personalizar as mensagens de erro do Zend_Validate.
Abraços
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
Fabio,
Talvez seja melhor você definir as mensagens diretamente no seu formulário.
Inclusive, vou preparar um post mostrando essa ideia.
Abraços
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.
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