Mostrando postagens com marcador Banco de Dados. Mostrar todas as postagens
Mostrando postagens com marcador Banco de Dados. Mostrar todas as postagens

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',
                )
        );
    }
}



1 de setembro de 2012

Herança no Doctrine: Persistindo e recuperando objetos

Em um artigo anterior foi apresentando como a herança pode ser implementada no Doctrine. Neste artigo vamos apresentar como os elementos da herança podem ser persistidos e recuperados do Banco de Dados

Para exemplo didático vamos utilizar novamente o exemplo épico do filme Star Wars (Figura 1), onde existe uma relação de herança entre: DarthVader, Luke Skywalker e Leia Organa.


Figura 1: Exemplo didático de herança. 



As classes que representam cada um dos elementos podem ser visualizadas no post anterior


Para o conjunto de classes do exemplo vamos implementar uma classe DAO (Data Access Object) para interagir com o Banco de Dados. A seguir é apresentado o código da classe DAO:

Classe JediDAO



 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
<?php

class JediDAO {
   
    public static function add($object) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();

        if($object->getId()){
            $object = $em->merge($object);
        }else{
            $em->persist($object);
        }
        
        $em->flush();

        return $object;
    }
    
    public static function get($id) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();
                       
        $object = $em->getRepository('DarthVader')->find($id);

        return $object;
    } // function
    
    public static function listAll(){
        /**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 obj from DarthVader obj');
        
        $object_list = $query->getResult();
        
        return $object_list;        
    }
    
} // class

Agora vamos testar os métodos implementados na classe DAO:


 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
<?php 
        //Criando um objeto DarthVader
        $darth_1 = new  DarthVader();
        $darth_1->setAtributoAnakin(1);
        
        //Persistindo o objeto
        JediDAO::add($darth_1);
        
        // Criando um objeto Luke
        $luke_1 = new Luke();
        $luke_1->setAtributoLuke(2);
        
        JediDAO::add($luke_1);
        
        //Criando um objeto Leia
        $leia_1 = new Leia();
        $leia_1->setAtributoLeia(3);
        
        JediDAO::add($leia_1);
        
        // Recuperando o objeto de id = 2
        $jedi_2 = JediDAO::get(2);
        
        /*
          var_dump em $jedi_2 retorna: 
            object(Luke)[198]
              private 'atributo_luke' => int 2
              private 'id' (DarthVader) => int 2
              private 'atributo_anakin' (DarthVader) => null

        */
        
        //Listando todos os objetos jedi's do Banco
        $lista_jedis = JediDAO::listAll();
        
        /*
        var_dump em $lista_jedis retorna um array:

        array (size=3)
        0 => 
            object(DarthVader)[209]
              private 'id' => int 1
              private 'atributo_anakin' => int 1
        1 => 
            object(Luke)[198]
              private 'atributo_luke' => int 2
              private 'id' (DarthVader) => int 2
              private 'atributo_anakin' (DarthVader) => null
        2 => 
            object(Leia)[208]
              private 'atributo_leia' => int 3
              private 'id' (DarthVader) => int 3
              private 'atributo_anakin' (DarthVader) => null
 
        */        


1 de agosto de 2012

Projeto exemplo integrando o Zend Framework e o Doctrine

O início sempre é a parte mais complicada para alguém que está aprendendo um determinado framework, pois ele se depara com uma quantidade grande de novas informações a serem "digeridas".  



Na maioria das vezes falta um projeto básico "Hello World" para apresentar as funcionalidades básicas para o usuário. Algo semelhante ao que ocorre no aprendizado das linguagens de programação.

Em função disto, o ZeDoc foi criado para apresentar um projeto (ou template) exemplo utilizando o Zend Framework em conjunto com o Doctrine, contendo algumas funcionalidades básicas para um projeto, como por exemplo:


Informações mais detalhadas sobre o projeto (como instalar, funcionalidades implementadas) podem ser encontradas em: no site do projeto, aqui mesmo (em futuros artigos) e ali (em futuros artigos).  

25 de julho de 2012

Implementando Herança no Doctrine

Nesse artigo vamos falar um pouco sobre a implementação de Herança no Doctrine. Como exemplo didático de herança, temos a épica relação entre DarthVader,  Luke Skywalker e Leia Organa no filme Star Wars (Figura 1). Em vista disto, vamos utilizar esta relação entre os personagens para ilustrar a implementação da herança no Doctrine


Figura: "I am your father". 

A herança no Doctrine é especificada através dos atributos: 


  • @DiscriminatorColumn: utilizado para indicar qual o elemento da hierarquia (classe) a linha da tabela representa.
  • @DiscriminatorMap: utilizado para identificar quais os valores que existirão na coluna do discriminador e qual classe da hierarquia está mapeado para cada valor.
  • @InheritanceType: representa a estrutura no Banco de Dados que irá armazenar a herança. SINGLE_TABLE indicada que tanto o objeto pai quanto os objetos filhos estarão representados na mesma tabela. JOINED indica que cada classe da hierarquia terá uma tabela própria. 


Por exemplo, tendo o mapa:

@DiscriminatorMap({"father" = "DarthVader", "son" = "Luke", "daughter" = "Leia"})

temos que father representa um objeto da classe DarthVader, já son representa um elemento da classe Luke.


A seguir um exemplo de implementação da herança. São especificadas três classes: DarthVader (classe pai), Luke (classe filho) e Leia (classe filho). 


Classe DarthVader (pai)



 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
<?php

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @Table(name="father")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"father" = "DarthVader", "son" = "Luke", "daughter" = "Leia"})
 */
class DarthVader{
    
    /**
     * @var integer $id
     * @Column(type="integer")
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $id;
    
    public function setId($id){$this->id = $id;}
    public function getId(){return $this->id;}
    
    /**
     * 
     * @Column(type="integer")
     * 
     */
    private $atributo_anakin;    
    
    public function setAtributoAnakin($atributo){$this->atributo_anakin=$atributo;}
    public function getAtributoAnakin(){return $this->atributo_anakin;}
}


Classe Luke (filho)


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

/**
 * 
 * @Entity
 * @Table(name="son") 
 */
class Luke extends DarthVader {
    
    /**
     * 
     * @Column(type="integer")
     * 
     */
    private $atributo_luke;    
    
    public function setAtributoLuke($atributo){$this->atributo_luke=$atributo;}
    public function getAtributoLuke(){return $this->atributo_luke;}
    
}


Classe Leia (filho)


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

/**
 * 
 * @Entity
 * @Table(name="daughter") 
 */
class Leia extends DarthVader {
    
    /**
     * 
     * @Column(type="integer")
     * 
     */
    private $atributo_leia;    
    
    public function setAtributoLeia($atributo){$this->atributo_leia=$atributo;}
    public function getAtributoLeia(){return $this->atributo_leia;}
    
    
}


A seguir a estrutura gerada no Banco de Dados para cada tipo de herança (InheritanceType).

JOINED


Figura: Tipo de Herança JOINED



SINGLE_TABLE



Figura: Tipo de Herança SINGLE_TABLE



Num próximo artigo vamos falar como ocorre o processo de persistência dos objetos Doctrine no Banco de Dados.