mardi 4 octobre 2011

OneToMany relationship in Doctrine2 and Symfony2 for dummies

It may seem obvious to a lot, but ...

The classes

In a forum, there are Authors. These authors can post messages. Every Message has one and only one Author, and an Author can write many Messages : this is typically a OneToMany relationship.
Here are the equivalent classes :
/**
 * @ORM\Entity
 * @ORM\Table(name="Author")
 * @ORM\Entity(repositoryClass="Acme\DemoBundle\AuthorRepository")
 */
class Author
{
 
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @var int
     */
    protected $id;
 
    /**
     * @ORM\OneToMany(targetEntity="Message", mappedBy="author", cascade={"persist", "remove"})
     */
    protected $messages;
    
    /**
     * Add message
     *
     * @param Acme\DemoBundle\Entity\Message $message
     */
    public function addMessage(Acme\DemoBundle\Entity\Message $message)
    {
        $this->mesages[] = $message;
        $message->setAuthor($this);
        return $this;
    }
    
    /**
     * Get messages
     *
     * @return Doctrine\Common\Collections\Collection 
     */
    public function getMessages()
    {
        return $this->messages;
    }

    
    public function __construct()
    {
        $this->messages = new \Doctrine\Common\Collections\ArrayCollection();
    }
}


/**
 * @ORM\Entity
 * @ORM\Table(name="Message")
 * @ORM\Entity(repositoryClass="Acme\DemoBundle\Repository\MessageRepository")
 */
class Message
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @var int
     */
    protected $id;
    
    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="messages", cascade={"persist", "update"})
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id", onDelete="cascade", onUpdate="cascade")
     * @var Acme\DemoBundle\Entity\Author
     */
    protected $author;
    
}
 

The issue


Now, let's say you want to transfer messages from author 2 to author 1 for some reason. Here is how to do it step by step :
// Get the entities
$Author1 = $authorRepository->find($idAuthor1);
$Author2 = $authorRepository->find($idAuthor2);

// Retrieve messages
$messagesOfAuthor2 = $Author2->getMessages();
Here is a visual description of what has happened :

State 0 :
We transfer each of the messages :
// Move message
foreach($messagesOfAuthor2 as $message)
{
    $Author1->addMessage($message);
    // Leads to state 1
    $Author2->getMessages()->removeElement($message);
    // Leads to state 2
}

State 1 :

State 2 :

Note the deletion of 1 link in the removeElement function, and the addition of 2 links in the addMessage function.
We can now remove the Author 2 and flush the EntityManager :
$entityManager->remove($Author2);

$entityManager->flush();

Aucun commentaire:

Enregistrer un commentaire