我有一个问题,让我的学说实体提取到我的ZF2表格。我对ZF2和Doctrine都很新(以及类表继承)。我已经阅读了几乎所有的ZF2和Doctrine文档,但似乎还无法弄清楚如何使其工作。
为了简要说明该系统,有一个名为Policy的主要实体。 Policy实体包括Proposer实体和PolicyProduct实体,以及其他几个列。
我在PolicyProduct实体中使用类表继承,因为我有3种不同的产品类型,每种类型都需要不同的数据。这3个产品实体是TouringCaravan,StaticCaravan和Parkhome。
Policy实体只能有1个Proposer和1个PolicyProduct。
所有实体都有每列的getter和setter方法。
表单im显示包括来自Policy实体和PolicyProduct实体的字段。
要显示表单,我首先获取Policy实体和Policy Fieldset。然后将Policy Fieldset设置为基础。
$policyEntity = $entityManager->getRepository('Policy\Entity\Policy')->find($policyId);
$policyFieldset = $formElementManager->get('policy_form_policy_fieldset');
$policyFieldset->setUseAsBaseFieldset(true);
然后我获取PolicyProduct特定的字段集并将其添加到policyFieldset。
eg
$productFieldset = $formElementManager->get('tourers_form_touring_fieldset');
$policyFieldset->add($productFieldset);
然后我将policyFieldset添加到表单中,将其与Policy实体绑定,并返回完成的表单。
$productForm->add($policyFieldset);
$productForm->bind($policyEntity);
return $productForm;
要注意,我使用DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator
作为每个字段集的保湿剂。然后,我在每个字段集的init()
方法中调用以下内容。
// Example from PolicyFieldset
$hydrator = new DoctrineHydrator($this->objectManager,true);
$this->setHydrator($hydrator)
->setObject(new Policy());
如果我填写表格并保存到数据库,我可以看到数据正确存储在表格中。如果我然后尝试与实体水合相同的表单,则不会映射PolicyProduct实体值。尽管如此,政策实体中的值也是正确的。
如果我转出$policyEntity->getPolicyProduct()
我可以看到所有数据,这意味着实体正确保存并检索信息,问题似乎是当我尝试将实体数据提取到表单字段集时。
我希望这是有道理的,但如果没有,请告诉我,我会尽力澄清。
由于
以下是主要实体
政策
namespace Policy\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="policy")
*/
class Policy {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="Proposer\Entity\Proposer", inversedBy="policy")
* @ORM\JoinColumn(name="proposer_id", referencedColumnName="id")
*
protected $proposer;
/**
* @ORM\ManyToOne(targetEntity="Product")
* @ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="RESTRICT")
*/
protected $product;
/**
* @ORM\OneToOne(targetEntity="Policy\Entity\PolicyProduct")
* @ORM\JoinColumn(name="policy_product_id", referencedColumnName="id")
*/
protected $policyProduct;
/**
* @ORM\ManyToOne(targetEntity="PolicyStatus")
* @ORM\JoinColumn(name="policy_status_id", referencedColumnName="id", onDelete="RESTRICT")
*/
protected $policyStatus;
/**
* @ORM\Column(name="policyInception", type="date", nullable=true)
*/
protected $policyInception;
// Omitted getters and setters
}
PolicyProduct
namespace Policy\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="policy_product")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="productDiscriminator", type="integer")
* @ORM\DiscriminatorMap({1 = "Tourers\Entity\TouringCaravan", 2 = "Statics\Entity\StaticCaravan", 3 = "Parkhomes\Entity\Parkhome"})
*/
class PolicyProduct {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// Omitted getters and setters
}
TouringCaravan - PolicyProduct Inherited Table的示例
namespace Tourers\Entity;
use Doctrine\ORM\Mapping as ORM;
use Policy\Entity\PolicyProduct;
/**
* @ORM\Entity
* @ORM\Table(name="touring_caravan")
*/
class TouringCaravan extends PolicyProduct {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\OneToOne(targetEntity="Policy\Entity\Policy")
* @ORM\JoinColumn(name="policy_id", referencedColumnName="id")
*/
protected $policy;
/**
* @ORM\ManyToOne(targetEntity="TouringCaravanMake")
* @ORM\JoinColumn(name="touring_caravan_make", referencedColumnName="id", onDelete="RESTRICT")
*/
protected $caravanMake;
/**
* @ORM\Column(name="caravanModel", type="string", length=128, unique=false, nullable=false)
*/
protected $caravanModel;
....
Lots more columns specific to the TouringCaravan Entity
// Omitted getters and setters
}
答案 0 :(得分:0)
看来你这里有太多实体了。如果我理解你要做的事情,每个政策都与一个“类”产品相关联,该产品将是TouringCaravan,StaticCaravan或Parkhome。如果是这种情况,那么您的鉴别器列属于您的策略实体,而PolicyProduct enitiy可能会消失。这是你想要做的:
1)在Policy\Entity\Policy
:
// ... //
/**
* @ORM\Entity
* @ORM\Table(name="policy")
* @ORM\InheritanceType("JOINED")
* @ORM\DiscriminatorColumn(name="policyProduct", type="integer")
* @ORM\DiscriminatorMap({1 = "Tourers\Entity\TouringCaravan", 2 = "Statics\Entity\StaticCaravan", 3 = "Parkhomes\Entity\Parkhome"})
*/
class Policy {
// ... //
并删除此内容:
/**
* @ORM\OneToOne(targetEntity="Policy\Entity\PolicyProduct")
* @ORM\JoinColumn(name="policy_product_id", referencedColumnName="id")
*/
protected $policyProduct;
1a)当你在这里时,你需要使用$proposer
转义*/
的DocBlock。
2)删除Policy\Entity\PolicyProduct
。
3)在Tourers\Entity\TouringCaravan
和所有其他子实体中进行此更改:
// ... //
class TouringCaravan extends Policy {
// ... //
4)考虑重命名你的id。每个实体都有自己的id,如果它们都被称为$ id,很容易丢失哪个实体。如果您的产品实体的ID为$product_id
,而您的TouringCaravan实体的ID为$touring_caravan_id
,依此类推,则更容易识别。我在我的表和我的实体中为我的id分配了唯一的描述性名称,并且我发现如果我忘记制作一些映射语句,Doctrine有时会为我建立连接。
5)。考虑从Tourers\Entity\TouringCaravan
和其他子实体中删除生成的子ID,并让数据库在表中生成值。我发现当一个实体扩展另一个实体并且JOIN中有两个自动编号列时,Doctrine不喜欢它。
你在这里有比你共享的更多(Proposer实体和PolicyStatus实体)所以我不能说这些建议是否会解决你的所有问题,但这是一个开始。
与您的问题无关的另一个建议:
您可以考虑将您的鉴别器列更改为字符串,而不是整数,并在那里记录产品的文本描述。否则,您将需要创建另一个实体或硬编码数组以指示1 = TouringCaravan,2 = StaticCaravan和3 = Parkhome。记录策略表中的文本还可以更容易地读取数据表,或者如果您需要,可以从单个实体创建索引视图。