验证后,ZF2表单删除嵌套集合

时间:2016-10-30 16:04:24

标签: doctrine-orm zend-framework2 zend-form

我有三个与Zend Form集合一起使用的相关Doctrine实体。

实体是InvoiceItems - > (一对多) - > InvoiceItemOptions - > (一对多)InvoiceItemOptionValues。

当我添加新项目时,所有选项和值都正确填充实体。但是,当我编辑项目时,值将从选项实体中删除。表单正确显示,以便从数据库中提取值,并且DoctrineObject水合器填充表单。验证表单后,这些值将丢失。

我的实体代码

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;

在我的田野中我有

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;
}

最后我的帖子数据

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
                )

        )

我正在使用Zend Framework版本2.5.1和Doctrine ORM模块版本1.0.0

希望有人知道这里发生了什么,非常感谢提前。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。

在表单验证之前添加行$this->form->setBindOnValidate(FormInterface::BIND_MANUAL);解决了这个问题。我还在验证后添加了$this->form->bind($this->entity);

希望这有助于某人。

修改

我还发现InvoiceItemOptions实体中的值的数组集合在水合期间没有被克隆,因此InvoiceItemOptionValues是错误的。我通过将魔术方法__clone()添加到我的InvoiceItemOptions实体来解决了这个问题。

public function __clone()
{
    $this->values = new ArrayCollection();
}