quarta-feira, 18 de julho de 2012

Auto relacionamento no DOCTRINE

Olá amigos tudo bem? Esse artigo é para vc que precisa fazer um auto relacionamento(Self-reference) utilizando o DOCTRINE.


Existem 3 formas de relacionamentos e vamos aborda-las aqui que são:
1. Um para Um (One-To-One)
2. Um para Muitos (One-To-Many)
3. Muitos para Muitos (Many-To-Many)



Podemos facilmente ter uma referência de qualquer um desses caras, vamos aos exemplos


1. Um para Um (One-To-One Doctrine)
Estudante para mentor, só pode ter um e ele também é estudante. (arrumando o exemplo antigo)



  
  1. <?php
  2. /** @Entity */
  3. class Estudante
  4. {
  5.     // ...
  6.  
  7.     /**
  8.      * @OneToOne(targetEntity="Estudante")
  9.      * @JoinColumn(name="mentor_id", referencedColumnName="id")
  10.      */
  11.     private $mentor;
  12.  
  13.     // ...
  14. }



O uso do @JoinColumn é opcional já que seria definido por padrão então pois cnh_id e o id são os mesmos, podemos omiti-lo por padrão.


2. Um para Muitos (One-To-Many)

Imagine um caso de um forum, onde uma opinião pode receber 'n' opiniões (opinião da opinião)



  1. class ForumOpiniao {
  2.     /**
  3.      * @OneToMany(targetEntity="ForumOpiniao", mappedBy="forum_opiniao", cascade={"persist", "remove"})
  4.      */
  5.     private $filhos;
  6.     /**
  7.      * @ManyToOne(targetEntity="ForumOpiniao", inversedBy="filhos")
  8.      * @JoinColumn(name="forum_opiniao", referencedColumnName="id")
  9.      */
  10.     private $forum_opiniao;
  11. //.....
  12. }

Veja que criamos o atributo forum_opiniao que referencia a ele mesmo e os filhos para armazenar os filhos desse pai.


3. Muitos para Muitos (Many-To-Many)

Um caso onde usuarios poderiam se referenciar



  1. <?php
  2. /** @Entity */
  3. class User
  4. {
  5.     // ...
  6.     /**
  7.      * @ManyToMany(targetEntity="User", mappedBy="myFriends")
  8.      */
  9.     private $friendsWithMe;
  10.     /**
  11.      * @ManyToMany(targetEntity="User", inversedBy="friendsWithMe")
  12.      * @JoinTable(name="friends",
  13.      *      joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
  14.      *      inverseJoinColumns={@JoinColumn(name="friend_user_id", referencedColumnName="id")}
  15.      *      )
  16.      */
  17.     private $myFriends;
  18.     public function __construct() {
  19.         $this->friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection();
  20.         $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection();
  21.     }
  22.     // ...
  23. }

Básico e prático não achou?



Fonte: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/reference/association-mapping.html

5 comentários:

  1. Caracaa brother valeu mesmo pelo artigo! Foi de muita utilidade mesmo! Doctrine é bom mais no começo é demais de complexo ainda mais para devs PHP da nata.

    ResponderExcluir
  2. Paulo no Muitos para Muitos sou obrigado a criar um construtor inicializando com o ArrayCollection do Doctrine? Não sei ao certo se no meu caso eu devo.

    ResponderExcluir
  3. O exemplo dado para o caso um para um, não é de um auto relacionamento, pois está envolvendo duas entidades diferentes: Motorista e CNH. Auto relacionamento deve envolver instancias de uma mesma classe.

    ResponderExcluir
    Respostas
    1. Realmente um erro bizzaro meu. Deixei passar em branco por eu estar prestando atenção apenas no n-2-n... de qualquer forma obrigado por lembrar... só espero que da próxima vez não comente como Anônimo... Críticas são bem vindas.
      Vou mudar o exemplo.

      Excluir
  4. Fiz isso e está dando um erro louco quando vou fazer o FindByOne, por exemplo! No meu caso eu fiz:

    class Membro_model
    {
    /**
    * @Id @Column(type="integer")
    * @GeneratedValue(strategy="IDENTITY")
    */
    public $id = 0;

    /**
    * @Column(type="string", columnDefinition="VARCHAR(50) NOT NULL")
    */
    public $nome = 0;

    /**
    * @Column(type="string", columnDefinition="VARCHAR(12) NOT NULL")
    */
    public $login = 0;

    /**
    * @OneToOne(targetEntity="Membro_model")
    * @JoinColumn(name="patrocinador_id", referencedColumnName="id")
    **/
    public $patrocinador;

    }

    Quando vou puxar linhas em que a coluna id_patrocinador da tabela não é nula, ele dá pau! Eu fiz:

    $membro = $this->doctrine->em->getRepository('Membro_model')->findBy(array('login' => $login));

    Não funciona! Saberia como resolver? Se puder agradeço: anderson.cavalcanti.rn@gmail.com

    ResponderExcluir