23 de novembro de 2012

Formulários no Doctrine: Validando a existência do login no Banco de Dados

Ao gerar um formulário para cadastro de usuários em um sistema, usualmente é desejado validar as informações inseridas pelos usuários nos campos do formulário. No caso de um campo que vai ser utilizado na identificação do usuário para este se logar no sistema (login), como por exemplo um apelido (nick) ou um email, deve-se ter a restrição de que nenhum outro usuário já esteja cadastrado com este campo. Um exemplo de duplicação do 'login' ocorre no filme Irmão Gêmeos, onde Julius Benedict (Arnold Schwarzenegger) e Vincent Benedict (Danny DeVito) possuem o mesmo código genético  


Figura 1: exemplo de duplicação de login.  


Neste artigo vai ser apresentado como a classe Zend_Validate_Abstract pode ser estendida para utilizar o Doctrine para validar se o login que está sendo inserido não existe no Banco de Dados. Caso já exista um usuário cadastrado com este login é retornado um código de erro. Além disto, vai ser apresentado um exemplo de como esta classe pode ser utilizado em um formulário de cadastro. 

A seguir é apresentada a classe DoctrineValidateEmail, que estende a Zend_Validate_Abstract e permite a validação do login (neste exemplo básico login = email do usuário). Basicamente nesta classe foi realizada a reimplementação da função isValid que utiliza uma classe DAO (UsuarioDAO) que valida o login passado como parâmetro.


Classe DoctrineValidateEmail


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php 

class DoctrineValidateEmail extends \Zend_Validate_Abstract{
    
    const NOK = 1;
    
    protected $_messageTemplates = array(
        self::NOK => "%value% já cadastrado"
    );
    
    public function isValid($email){
        
        try{
            $user = UserDAO::getUserByEmail($email);
        }catch(\Doctrine\ORM\NoResultException $e){
            // Email livre para cadastro
            $user = null;
        }
        if($user){
            $this->_error(self::NOK,$email);
            return false;
        }
        return true;
    }
}

A classe UserDAO que interage com o Banco de Dados utilizando o Doctrine é apresentada a seguir. Para simplificar o exemplo é apresentado apenas a implementação do método getUserByEmail utilizado pela DoctrineValidateEmail.


Classe DAO para interação com o Banco de Dados


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

class UserDAO {
    
    public static function getUserByEmail($email) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();
               
        
        $query = $em->createQuery('select s from UserDoctrine s WHERE s.email = ?1');
        $query->setParameter(1, $email);
        
        $user_doctrine = $query->getSingleResult();
        
        return $user_doctrine;        
    } // function
} // class


E finalmente é apresentado como a classe DoctrineValidateEmail implementada pode ser utilizada em um formulário para validar o login que está sendo inserido pelo usuário.


Exemplo de Formulário


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php

class Cadastro_Form_Cadastro extends Zend_Form
{

    public function init()
    {
        $this->setMethod('post');

        // CSFR (www.frameword.zend.com/manual/en/learning.quickstart.create-form.html)
        $this->addElement('hash', 'csrf', array('ignore' => true));

        // Nome
        $this->addElement(
                'text', 'nome', array(
            'label' => 'Nome:',
            'required' => true,
            'maxlength' => '30',        
            'filters' => array('StringTrim'),
        ));

        // Sobrenome
        $this->addElement(
                'text', 'sobrenome', array(
            'label' => 'Sobrenome:',
            'required' => true,
            'maxlength' => '30',        
            'filters' => array('StringTrim'),
        ));
  
        // Email vai ser utilizado como login
        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email:');
        $email->addFilters(array('StringTrim', 'StripTags'));
        $email->addValidator('EmailAddress', TRUE);
        $email->setRequired(true);

        //Adicionando a validação no email                
        $email->addValidator(new DoctrineValidateEmail($email->getValue()));

        $this->addElement($email);

        //Senha        
        $this->addElement(
                'password', 'password', array(
            'label' => 'Senha:',
            'required' => true,
            'maxlength' => '20',        
                )
        );

        $this->addElement(
                'submit', 'submit', array(
            'ignore' => true,
            'label' => 'Cadastrar',
                )
        );
    }
}