Я новичок в Doctrine2 и пытаюсь создать сущности для следующей структуры БД:
Я хочу, чтобы все части машины были массивом в одном атрибуте класса машины. Я попробовал это:
class Machine {
....
/**
* @var array
* @ORM\OneToMany(targetEntity="MachineHasPart", mappedBy="machine", cascade={"persist", "remove"}, orphanRemoval=TRUE)
*/
private $parts;
....
public function getParts () {
return array_map(
function ($machineHasPart) {
return $machineHasPart->getPart();
},
$this->parts->toArray()
);
}
}
куда MachineHasPart
это @MappedSuperclass
для промежуточных сущностей / таблиц (типа machineHasCylinder
и т.д.), но это не удалось с:
Возникла исключительная ситуация при выполнении команды SELECT FROM machineHasPart t0.
Должен ли я реструктурировать свою базу данных, чтобы использовать ORM здесь? Или есть решение для моего случая?
Вы не можете запросить @MappedSuperClass
, Это также упоминается в Документация Doctrine2 в главе 6.1. Сопоставленные суперклассы:
Сопоставленный суперкласс не может быть сущностью, он не способен выполнять запросы и является постоянным
Это означает, что вы должны либо изменить целевой объект на что-то запрашиваемое, либо вы должны сделать MachineHasPart
к сущности и изменить на наследование одной таблицы.
Когда я смотрю на вашу структуру базы данных, я бы предложил изменить вашу Machine
юридическое лицо, чтобы иметь три независимых отношения для частей. Один для Пояса, один для Цилиндра и один для Гира.
Тогда вместо общего getParts
у тебя будет три метода getBelts
, getCylinders
а также getGears
,
Если это действительно не то, что вы хотите, то вы можете оставить комментарий.
Вы можете решить это также с наследованием классов. Сначала сделайте базовый класс Part
это также сущность и использовать его в других классах Belt
, Cylinder
а также Gear
:
Часть:
<?php
namespace Machine\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Part
*
* @ORM\Entity
* @ORM\Table("part")
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="discriminator", type="string")
* @ORM\DiscriminatorMap({
* "part" = "Part",
* "gear" = "Gear",
* "cylinder" = "Cylinder",
* "belt" = "Belt",
* })
* @property int $id
*/
class Part
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var Machine
* @ORM\ManyToOne(targetEntity="Machine\Entity\Machine", inversedBy="parts")
* @ORM\JoinColumn(name="machine_id", referencedColumnName="id", nullable=true)
*/
protected $machine;
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* @param int $id
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
//... add setters and getters for machine as normal ...
}
Расширьте этот класс в других ваших частях:
Пояс:
<?php
namespace Machine\Entity;
/**
* Belt
*
* @ORM\Entity
*/
class Belt extends Part
{
}
цилиндр:
<?php
namespace Machine\Entity;
/**
* Cylinder
*
* @ORM\Entity
*/
class Cylinder extends Part
{
}
Коробка передач:
<?php
namespace Machine\Entity;
/**
* Gear
*
* @ORM\Entity
*/
class Gear extends Part
{
}
Теперь в вашей машине относятся к деталям примерно так.
Машина:
<?php
namespace Machine\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Machine
*
* @ORM\Entity
* @ORM\Table("machine")
* @property int $id
*/
class Machine
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
*
* @param int $id
* @return self
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* @var Collection
* @ORM\OneToMany(targetEntity="Machine\Entity\Part", mappedBy="machine")
*/
protected $parts;
public function __constuct()
{
$parts = new ArrayCollection();
}
/**
*
* @return Collection
*/
public function getParts()
{
return $this->parts;
}
//... add setters and getters for parts as normal ...
}
Расширьте этот класс в других ваших частях:
Читая дальше в Документация Doctrine2 в главе 6.1. Сопоставленные суперклассы (упоминается @Wilt):
… Кроме того, ассоциации «многие ко многим» возможны только в том случае, если сопоставленный суперкласс используется только в одном объекте в данный момент …
Это означает, что в этом случае сопоставление ORM не помогает. Я не могу собрать данные всех трех объектов MachineHasCylinder, MachineHasBelt и MachineHasGear одновременно с помощью MappedSupperclass.
Я думаю, используя DQL или же Родной SQL это единственное решение этой проблемы.