Reputation: 33
I am working with Symfony2 and Doctrine2 and I have an object that needs to implement multiple arrays of arrays. The only solution I came up with is to create a bridge object between my main object and the object it is referencing.
So this would be my object:
/**
* @ORM\Table()
*/
class MyObject
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="CollectionOfObjectX", mappedBy="parent", cascade={"all"})
**/
private $collectionsOfObjectX;
public function __construct() {
$this->collectionsOfObjectX = new ArrayCollection();
}
... (Getters and Setters)
}
This would be the Bridge between the object and some other object
/**
* @ORM\Table()
*/
class CollectionOfObjectX
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="ObjectX", inversedBy="collectionsOfObjectX", cascade={"all"})
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
**/
private $parent;
/**
* @ORM\ManyToMany(targetEntity="MyObject", cascade={"all"})
* @ORM\JoinTable(
* joinColumns={@ORM\JoinColumn(name="local_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="foreign_id", referencedColumnName="id")}
* )
**/
private $items;
public function __construct() {
$this->items = new ArrayCollection();
}
.... (Getters and Setters)
}
And this would be the referenced object
/**
* @ORM\Table()
*/
class ObjectX
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
... (Some Properties, Getters and Setters)
}
So while this works, it requires a Bridge Object for each possible relation between MyObject and any other object it references, implying a lot of duplicate code.
Is there a better way?
Upvotes: 2
Views: 1608
Reputation: 111
Doctrine 2 does not genuinely provide n-2-n abstract relationship. Object A must be a known class, and it should reference Object B (also a known class).
I would suggest trying something like this, to workaround
/**
* @ORM\Table()
*/
class MyObject
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="CollectionOfObjectXYZ", mappedBy="parent", cascade={"all"})
**/
private $collectionsOfObjectXYZ;
public function __construct() {
$this->collectionsOfObjectXYZ= new ArrayCollection();
}
... (Getters and Setters)
}
Notice the missing Annotations
/**
* @ORM\Table()
*/
class CollectionOfObjectXYZ
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="MyObject", inversedBy="collectionsOfObjectXYZ", cascade={"all"})
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
**/
private $parent;
private $items;
public function __construct() {
$this->items = new ArrayCollection();
}
public function addItem($item){
/** EDIT : since we store the relation in the final object (X Y Z), we don't need particular annotation here **/
$item->setCollectionOfObjectXYZ($this);
return $this;
}
.... (Getters and Setters)
}
/**
* @ORM\Table()
*/
class ObjectX
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var CollectionOfObjectXYZ
*
* @ORM\ManyToOne(target="CollectionOfObjectXYZ", cascade={"persist"})
*/
private $colletion;
... (Some Properties, Getters and Setters)
}
/**
* @ORM\Table()
*/
class ObjectY
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var CollectionOfObjectXYZ
*
* @ORM\ManyToOne(target="CollectionOfObjectXYZ", cascade={"persist"})
*/
private $colletion;
... (Some Properties, Getters and Setters)
}
Let me know if it helps.
Upvotes: 1