Reputation: 1485
I have three related Doctrine entities that I am trying to use with Zend Form collections.
The entities are InvoiceItems -> (one to many) -> InvoiceItemOptions -> (one to many) InvoiceItemOptionValues.
When I add a new item all options and values are populating the entity correctly. However when I edit a item the values are being removed from the options entity. The form displays correctly so the values are being pulled from the database and DoctrineObject hydrator is populating the form. The values are lost after the form is validated.
My entity code
InvoiceItems
/**
* @var \Doctrine\ORM\PersistentCollection
*
* @ORM\OneToMany(targetEntity="Application\Entity\InvoiceItemOptions", cascade={"persist"}, orphanRemoval=true, mappedBy="invoiceItem")
* })
*/
private $options;
InvoiceItemOptions
/**
* @var \Application\Entity\InvoiceItems
*
* @ORM\ManyToOne(targetEntity="Application\Entity\InvoiceItems", cascade={"persist"}, inversedBy="options")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="invoice_item_id", referencedColumnName="invoice_item_id")
* })
*/
private $invoiceItem;
/**
* @var \Doctrine\ORM\PersistentCollection $values
*
* @ORM\OneToMany(targetEntity="Application\Entity\InvoiceItemOptionValues", cascade={"persist"}, orphanRemoval=true, mappedBy="invoiceItemOption")
* })
*/
private $values;
InvoiceItemOptionValues
/**
* @var integer
*
* @ORM\Column(name="invoice_item_option_value_id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $invoiceItemOptionValueId;
/**
* @var \Application\Entity\InvoiceItemOptions
*
* @ORM\ManyToOne(targetEntity="Application\Entity\InvoiceItemOptions", cascade={"persist"}, inversedBy="values")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="invoice_item_option_id", referencedColumnName="invoice_item_option_id")
* })
*/
private $invoiceItemOption;
/**
* @var string
*
* @ORM\Column(name="value", type="text", length=65536, nullable=false)
*/
private $value;
/**
* @var string
*
* @ORM\Column(name="price", type="decimal", precision=9, scale=2, nullable=false)
*/
private $price;
And in my fieldsets I have
InvoiceItemFieldset
$this->add(array(
'type' => 'Collection',
'name' => 'options',
'options' => array(
'count' => 0,
'should_create_template' => TRUE,
'template_placeholder' => '__OPTION__',
'allow_add' => TRUE,
'allow_remove' => TRUE,
'target_element' => $this->invoiceItemOptionFieldset,
),
));
InvoiceItemOptionFieldset
$this->add(array(
'type' => 'Collection',
'name' => 'values',
'options' => array(
'count' => 0,
'should_create_template' => TRUE,
'template_placeholder' => '__VALUE__',
'target_element' => $this->invoiceItemOptionValuesFieldset,
),
));
InvoiceItemOptionValuesFieldset
public function init()
{
$this->add(array(
'name' => 'invoiceItemOptionValueId',
'type' => 'Hidden'
));
$this->add(array(
'name' => 'value',
'type' => 'Textarea',
'options' => array(
'label' => _('Value:'),
'label_attributes' => array('class' => 'required'),
),
'attributes' => array(
'cols' => 30,
'rows' => 5,
),
));
$this->add(array(
'name' => 'price',
'type' => 'Text',
'options' => array(
'label' => _('Price Inc. VAT:'),
),
'attributes' => array(
'size' => 10,
'maxlength' => 10,
),
));
}
EditItemModel
use Zend\Stdlib\Parameters;
...
public function processForm(Parameters $postData)
{
$entityManager = $this->getEntityManager();
$this->form->setData($postData);
if ($this->form->isValid()) {
// values lost here
$this->form->bind($this->entity);
$this->setFormValid(TRUE);
if ($this->entity->getQuantity() < 1) {
$this->entity->setQuantity(1);
}
$goodsTotal = $this->entity->getPriceEachIncVat() * $this->entity->getQuantity();
$optionsTotal = 0.00;
foreach ($this->entity->getOptions() as $option) {
foreach ($option->getValues() as $value) { // entity has no values
if ($value->getPrice() > 0) {
$optionsTotal = $optionsTotal + ($value->getPrice() * $this->entity->getQuantity());
}
}
}
$this->invoiceModel->calculateItemsVat($this->entity, $goodsTotal, $optionsTotal);
$entityManager->persist($this->entity);
if ($this->flushEntityManager($entityManager)) {
return $this->invoiceModel->calculateInvoiceTotals($this->getInvoice()->getInvoiceId());
}
}
return FALSE;
}
Finally my post data
Array
(
[items] => Array
(
[options] => Array
(
[0] => Array
(
[name] => Test Option 0
[invoiceItemOptionId] => 37
[values] => Array
(
[0] => Array
(
[value] => Test Option 0 Value 0
[price] => 0.00
[invoiceItemOptionValueId] => 37
)
[1] => Array
(
[value] => Test Option 0 Value 1
[price] => 29.99
[invoiceItemOptionValueId] => 38
)
)
)
)
[title] => Title
[sku] =>
[quantity] => 2
[priceEachIncVat] => 1000.00
[vatRate] => 1
[invoiceItemId] => 20
)
)
I am using Zend Framework version 2.5.1 and Doctrine ORM Module version 1.0.0
Hopefully someone knows what is going on here, many thanks in advance.
Upvotes: 0
Views: 86
Reputation: 1485
I have found a solution.
Adding the line $this->form->setBindOnValidate(FormInterface::BIND_MANUAL);
before form validation solved the problem. I also added $this->form->bind($this->entity)
after validation;
Hope this helps someone.
EDIT
I also found that the array collection for values in InvoiceItemOptions entity was not being cloned during hydration so the InvoiceItemOptionValues were wrong. I solved this issue by adding the magic method __clone() to my InvoiceItemOptions entity.
public function __clone()
{
$this->values = new ArrayCollection();
}
Upvotes: 1