I find the documentation very poor when it comes to explaining the creation of relationships between entities. So, i'll have to ask for help to my fellow StackExchangers. So, i'm trying to build the following cases:
Case 1
A User
belongs to one or more Group
, and a Group
can have many Permission
. A User
also can have a Permission
.
Case 2
A Ticket
has a Category
, multiple Tag
and multiple Comment
.
Thanks in advance!
Sure thing. First thing to understand is that there is no "one way" to do this. Doctrine gives a lot of flexibility in terms of how you define the relationship - even if multiple definitions produce the exact same DDL (and this is important to understand - some of the mapping choices only effect the object-side of the ORM, not the model-side)
Here's your Users/Groups/Permissions example, which are actually all many-to-many associations (I excluded all non-relevant but required code, like PK column definition)
<?php
namespace Your\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
*/
class User
{
/**
* Many-To-Many, Unidirectional
*
* @var ArrayCollection $groups
*
* @ORM\ManyToMany(targetEntity="Group")
* @ORM\JoinTable(name="user_has_group",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* Many-To-Many, Unidirectional
*
* @var ArrayCollection $permissions
*
* @ORM\ManyToMany(targetEntity="Permission")
* @ORM\JoinTable(name="user_has_permission",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")}
* )
*/
protected $permissions;
public function __construct()
{
$this->groups = new ArrayCollection();
$this->permissions = new ArrayCollection();
}
}
/**
* @ORM\Entity
*/
class Group
{
/**
* Many-To-Many, Unidirectional
*
* @var ArrayCollection $permissions
*
* @ORM\ManyToMany(targetEntity="Permission")
* @ORM\JoinTable(name="group_has_permission",
* joinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="permission_id", referencedColumnName="id")}
* )
*/
protected $permissions;
public function __construct()
{
$this->permissions = new ArrayCollection();
}
}
/**
* @ORM\Entity
*/
class Permission {}
If you have questions about what's going on here, let me know.
Now, to your second example
<?php
namespace Your\Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
*/
class Ticket
{
/**
* Many-To-One, Unidirectional
*
* @var Category
*
* @ORM\ManyToOne(targetEntity="Category")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
/**
* Many-To-Many, Unidirectional
*
* @var ArrayCollection $permissions
*
* @ORM\ManyToMany(targetEntity="Tag")
* @ORM\JoinTable(name="tickt_has_tag",
* joinColumns={@ORM\JoinColumn(name="ticket_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
* )
*/
protected $tags;
/**
* One-To-Many, Bidirectional
*
* @var ArrayCollection $comments
*
* @ORM\OneToMany(targetEntity="Comment", mappedBy="ticket")
*/
protected $comments;
public function __construct()
{
$this->tags = new ArrayCollection();
$this->comments = new ArrayCollection();
}
}
/**
* @ORM\Entity
*/
class Comment
{
/**
* Many-To-One, Bidirectional
*
* @var Ticket $ticket
*
* @ORM\ManyToOne(targetEntity="Ticket")
* @ORM\JoinColumn(name="ticket_id", referencedColumnName="id")
*/
protected $ticket=null;
}
/**
* @ORM\Entity
*/
class Tag {}
/**
* @ORM\Entity
*/
class Category {}
As before, let me know if you want any of this explained.
P.S. None of this was actually tested, I just kinda banged it out in my IDE real fast. There might be a typo or two ;)
Try this:
Class User {
/**
* @ORM\OneToMany(targetEntity="path\to\group", mappedBy="user", cascade={"persist", "remove"})
*/
private $group;
You will have One to Many relation between User
and Group
.. The targetEntity
is the path to the Entity that you want have a relationship with, the mappedBy
is the variable from the Group
Entity. cascade
means User
can add to Group
and remove from Group
Class Group {
/**
* @ORM\ManyToOne(targetEntity="path\to\user, inversedBy="group")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
This is the reserve side of the relationship.. targetEntity
should have the path back to the parent entity, which is User
in this case. inversedBy
is the variable from the User
Entity. JoinColumn
is just telling Doctrine what to join on, this is automatically done if you don't set it yourself.