在 Zend 框架 2 中使用 MappedSuperclass 的 Doctrine 2 多对多
Posted
技术标签:
【中文标题】在 Zend 框架 2 中使用 MappedSuperclass 的 Doctrine 2 多对多【英文标题】:Doctrine 2 many-to-many with MappedSuperclass in Zend framework 2 【发布时间】:2015-08-03 00:12:33 【问题描述】:我是 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 吗?或者我的情况有解决方案吗?
【问题讨论】:
能否在问题中包含完整的错误文本?我会很有用的。 【参考方案1】:您无法查询@MappedSuperClass
。 Doctrine2 documentation in chapter 6.1. Mapped Superclasses中也提到了这一点:
映射的超类不能是实体,它不可查询且不可持久
这意味着您必须将目标实体更改为可查询的对象,或者您必须将MachineHasPart
设置为实体并更改为single table inheritance。
当我查看您的数据库结构时,我建议将您的 Machine
实体更改为具有三个独立的部件关系。一个用于皮带,一个用于气缸,一个用于齿轮。
然后,您将拥有三个方法 getBelts
、getCylinders
和 getGears
,而不是通用的 getParts
。
如果这真的不是你想要的,那么你可以发表评论。
更新
你也可以通过类继承来解决它。首先创建一个基类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 ...
在你的其他部分扩展这个类:
【讨论】:
感谢您的回复。问题是实际上有超过 3 个实体作为“部分”。因此,不适合为例如的每个实体添加一个方法。 20个零件。我还需要它们按“sort_order”属性排序。 @Sbay 我明天会回复另一个可以满足您需求的解决方案。 谢谢@Wilt,期待。 @Sbay,检查我的更新。如果在实施过程中有任何问题,请发表评论。 感谢@Wilt 的更新。问题:哪个表上的哪一列是行的鉴别器:@ORM\DiscriminatorColumn(name="discriminator", type="string")
你能告诉我数据库表应该是什么样子吗?因为您的解决方案似乎假设所有部分都具有相似的属性(事实并非如此)。提前谢谢你。【参考方案2】:
进一步阅读Doctrine2 documentation in chapter 6.1. Mapped Superclasses(@Wilt 引用):
...此外,只有当映射的超类目前仅在一个实体中使用时,多对多关联才是可能的...
这意味着在这种情况下,ORM 映射没有帮助。我无法同时通过 MappedSupperclass 收集所有三个实体 MachineHasCylinder、MachineHasBelt 和 MachineHasGear 的数据。 我认为使用DQL 或Native SQL 是解决此问题的唯一方法。
【讨论】:
DQL 如何帮助您解决这个问题? DQL 是一种用于查询数据库模型的对象查询语言。当您使用 DQL 时,数据库模型本身不会有所不同,因此它无法解决您的问题。以上是关于在 Zend 框架 2 中使用 MappedSuperclass 的 Doctrine 2 多对多的主要内容,如果未能解决你的问题,请参考以下文章
如何在 zend 框架 2 或 AjaxContext 中使用 ajax?
在 Zend 框架 2 中使用 MappedSuperclass 的 Doctrine 2 多对多