Reputation: 598
I have a question about using Doctrine ORM's Class Table inheritance (CTI) with ZF2's Zend\Form
. In our system each user can have multiple roles, and these roles are defined through a class-table inheritance scheme so that we can define role-specific profile fields (ie: "grade level" is only applicable to student accounts). To construct this, there is an Account
entity with a OneToMany association to Account\Role
(the CTI "base" class):
<?php
namespace CdliPortal\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="account")
*/
class Account implements AccountInterface
{
// Other Fields Omitted
/**
* @ORM\OneToMany(targetEntity="CdliPortal\Entity\Account\Role", mappedBy="account", cascade={"ALL"})
*/
protected $roles;
}
I've already set up a Zend\Form
instance which binds an Account
entity (I followed the example from the DoctrineModule
documentation), and everything appears to be working A-OK...except for the CTI collection. In my Form object I add a Zend\Form\Element\Collection
member:
$roles = $user->getRoles();
if ( count($roles) > 0 ) {
$formAccount->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'roles',
'options' => array(
'count' => count($roles),
'target_element' => $this->serviceLocator->get('cdliportal_form_account_role'),
),
));
}
However, as you can see above, when setting up the roles
field the target_element
(in this case a fieldset) is specified at the collection level, which means that the collection must be uniform. For my above-described case I would need to be able to specify the target_element
individually for each element of the collection, depending on which member of the CTI it represents.
Any ideas / advice on how I could achieve this in a way that would still allow the elements of the collection to be automatically populated when I bind an Account object?
Upvotes: 2
Views: 909
Reputation: 598
I've hacked my way into a solution which works for my use case: build a custom NonuniformCollection
form element which is passed a collection of prototypes (one for each of the CTI entities) and clones the appropriate ones when the element is populated.
I've placed the code in a Gist here: https://gist.github.com/adamlundrigan/5195646
One caveat is that the template functionality no longer works as it doesn't know which prototype to use.
I'm still open to being shown a cleaner way to achieve this if anyone out there has any advice :)
Upvotes: 1