Я работаю с Symfony2 и Doctrine2, и у меня есть объект, который должен реализовать несколько массивов массивов. Единственное решение, которое я придумал, — это создать объект моста между моим основным объектом и объектом, на который он ссылается.
Так что это будет мой объект:
/**
* @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)
}
Это был бы мост между объектом и другим объектом
/**
* @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)
}
И это будет объект ссылки
/**
* @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)
}
Таким образом, хотя это работает, для каждого возможного отношения между MyObject и любым другим объектом, на который он ссылается, требуется объект Bridge, что подразумевает много дублирующегося кода.
Есть ли способ лучше?
Доктрина 2 действительно не дает n-2-n абстрактных отношений. Объект A должен быть известным классом, и он должен ссылаться на Объект B (также известный класс).
Я бы предложил попробовать что-то вроде этого, чтобы обойти
/**
* @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)
}
Обратите внимание на отсутствующие аннотации
/**
* @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)
}
Дайте мне знать, если это поможет.
Других решений пока нет …