ZF2 + Doctrine 2类表继承提取

时间:2013-11-18 11:56:58

标签: php doctrine-orm zend-framework2 zend-form class-table-inheritance

我有一个问题,让我的学说实体提取到我的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
}

1 个答案:

答案 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。记录策略表中的文本还可以更容易地读取数据表,或者如果您需要,可以从单个实体创建索引视图。