1

Im having an issue with getting my doctrine entity to extract to my ZF2 form. Im fairly new to both ZF2 and Doctrine (as well as class table inheritance). I've read through practically all of the ZF2 and Doctrine documentation, but still cant seem to figure out how to get this working.

To briefly explain the system, there is a main entity called Policy. The Policy entity includes a Proposer entity and a PolicyProduct entity, as well as a couple of other columns.

I am using Class Table Inheritance in the PolicyProduct entity, as I have 3 different product types, each with different data required. The 3 product entities are TouringCaravan, StaticCaravan and Parkhome.

The Policy entity can only have 1 Proposer and 1 PolicyProduct.

All entities have getter and setter methods for each column.

The form im displaying includes fields from both the Policy entity and the PolicyProduct entity.

To display the form, i first get the Policy entity and Policy Fieldset. And then set the Policy Fieldset as the base.

$policyEntity = $entityManager->getRepository('Policy\Entity\Policy')->find($policyId);
$policyFieldset = $formElementManager->get('policy_form_policy_fieldset');
$policyFieldset->setUseAsBaseFieldset(true);

I then get the PolicyProduct specific fieldset and add it to the policyFieldset.

eg
$productFieldset = $formElementManager->get('tourers_form_touring_fieldset');
$policyFieldset->add($productFieldset);

I then add the policyFieldset to the form, bind it with the Policy entity, and return the completed form.

$productForm->add($policyFieldset);
$productForm->bind($policyEntity);
return $productForm;

To note, i am using the DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator as my hydrator for each fieldset. I then call the following inside the init() method of each fieldset.

// Example from PolicyFieldset
$hydrator = new DoctrineHydrator($this->objectManager,true);

$this->setHydrator($hydrator)
     ->setObject(new Policy());

If i complete the form and save to the database, i can see that the data is stored correctly in the tables. If i then try to hydrate the same form with the entity, none of the PolicyProduct Entity values are mapped. The values in the Policy Entity are hydrated correctly though.

If i dump out $policyEntity->getPolicyProduct() i can see all the data, which means that the entity is correctly saving and retrieving the information, the problem appears to be when i try to extract the entity data to the form fieldset.

I hope this makes sense, but let me know if not and i'll try to clarify.

Thanks


Here are the main entities

Policy

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 - example of a 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
}
mikeaag
  • 11
  • 3

1 Answers1

0

It appears that you’ve got one too many entities here. If I understand what you’re trying to do, each policy is associated with a single “class” of product that will be either a TouringCaravan, a StaticCaravan or a Parkhome. If that is the case, then your discriminator column belongs in your Policy entity and the PolicyProduct enitiy can just go away. Here’s what you want to do:

1) Make this change in 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 {

// ... //

and remove this:

/**
* @ORM\OneToOne(targetEntity="Policy\Entity\PolicyProduct")
* @ORM\JoinColumn(name="policy_product_id", referencedColumnName="id")
*/
protected $policyProduct;

1a) While you’re here, you need to escape the DocBlock for $proposer with */.

2) Delete Policy\Entity\PolicyProduct.

3) Make this change in Tourers\Entity\TouringCaravan and all the other child entities:

// ... //

class TouringCaravan extends Policy {

// ... //

4) Consider renaming your id’s. Each of the entities has its own id, and it’s easy to lose track of which is which if they’re all called $id. If your Product entity’s id is $product_id, and your TouringCaravan entity’s id is $touring_caravan_id, and so on, they are easier to identify. I assign unique, descriptive names to my id’s in both my tables and my entities, and I have found that Doctrine will sometimes make the connection for me if I forget to make some of my mapping statements.

5). Consider removing the generated child ids from Tourers\Entity\TouringCaravan and the other child entities, and have your database generate the values in the table. I have found that Doctrine doesn’t like it when one entity extends another and there are two autonumber columns in the JOIN.

You’ve got a lot more going on here than you have shared (Proposer entity and PolicyStatus entity) so I can’t say if these suggestions will solve all of your problems, but it’s a start.

Another suggestion that is unrelated to your question:

You might consider changing your discriminator column to a string, rather than an integer, and recording the textual description of the product there. Otherwise, you’ll need to create yet another entity or hard code an array to indicate that 1 = TouringCaravan, 2 = StaticCaravan and 3 = Parkhome. Recording the text in the policy table will also make it easier to read your data tables or to create an index view from a single entity if you ever find the need to.

jcropp
  • 1,236
  • 2
  • 10
  • 29
  • 1
    @mikeaag did you actually try what jcropp suggested. Would be nice to give some feedback here... – Wilt May 08 '14 at 13:10