Symfony2表单集合不允许在更新时设置其他实体

时间:2014-08-07 11:07:03

标签: php forms symfony doctrine-orm

我们已按照AcmePizzaBundle提供的示例进行操作。 我们有DeliveryType表单,其中包含日期字段和deliveryItems集合,如下所示:

$builder
    ->add('date', 'date', array(
            'widget' => 'single_text',
            'datepicker' => true
    ))
    ->add('deliveryItems', 'collection', array(
        'type'         => new DeliveryItemType(),
        'allow_add'    => true,
        'allow_delete' => true,
        'prototype'    => true,
        'by_reference' => false,
    ))
;

Delivery实体与DeliveryItem实体保持关系:

/**
 * @var \Doctrine\Common\Collections\ArrayCollection
 *
 * @ORM\OneToMany(targetEntity="DeliveryItem", mappedBy="delivery", cascade={"persist", "remove"}, orphanRemoval=true)
 * @Assert\NotBlank()
 */
private $deliveryItems;

当我们创建一个交付时,有4个相关的DeliveryItems似乎一切正常。这可以使用createAction中的以下代码:

...

if ($form->isValid()) {

    $em->persist($entity);
    $em->flush();

...

如果我们然后去编辑此传递,我们就会遇到一个问题,如果我们添加一个额外的DeliveryItem(现在总共5个),那么就会出现一个问题。这是updateAction的控制器:

/**
 * Edits an existing Delivery entity.
 *
 * @Route("/{id}", name="delivery_update")
 * @Method("PUT")
 * @Template("AcmeAppBundle:Delivery:edit.html.twig")
 */
public function updateAction(Request $request, $id)
{
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('AcmeAppBundle:Delivery')->find($id);

    if (!$entity) {

        return new RedirectResponse($this->generateUrl('delivery'));
    }

    $deleteForm = $this->createDeleteForm($id);

    $editForm = $this->createForm(new DeliveryType(), $entity, array(
        'action' => $this->generateUrl('delivery_update', array('id' => $entity->getId())),
        'method' => 'PUT',
    ));
    $form->add('submit', 'submit', array('label' => 'Update'));

    $editForm->handleRequest($request);

    if ($editForm->isValid()) {

        $em->getConnection()->beginTransaction(); // transaction

        try {

            $em->persist($entity);
            $em->flush();
            $em->getConnection()->commit(); // transaction

            return $this->redirect($this->generateUrl('delivery_show', array('id' => $id)));

        } catch (Exception $e) {

            $em->getConnection()->rollback(); // transaction

            $entity = new Delivery();

            return $this->redirect($this->generateUrl('delivery'));

        }

    }

    return array(
        'entity'      => $entity,
        'edit_form'   => $editForm->createView(),
        'delete_form' => $deleteForm->createView(),
    );
}

有趣的是,如果我们print_r($request),似乎只保留了第一个项目,然后所有其他字段最终会更新我们添加的更多项目(在此示例中我们有4个并且我们添加了5,覆盖第二个字段):

[request] => Symfony\Component\HttpFoundation\ParameterBag Object
        (
            [parameters:protected] => Array
                (
                    [_method] => PUT
                    [northerncam_appbundle_delivery] => Array
                        (
                            [date] => 2014-08-07
                            [poNumber] => 345
                            [deliveryItems] => Array
                                (
                                    [0] => Array
                                        (
                                            [stock] => 1
                                            [quantity] => 1
                                        )

                                    [1] => Array
                                        (
                                            [stock] => 1
                                            [quantity] => 5
                                        )

                                    [2] => Array
                                        (
                                            [stock] => 1
                                            [quantity] => 3
                                        )

                                    [3] => Array
                                        (
                                            [stock] => 1
                                            [quantity] => 4
                                        )

                                )

                            [submit] => 
                            [_token] => QpaKjcOP35kDBC1EAW8dDGpugtoxF4-MhL5rC6pYTVU
                        )

                )

        )

更奇怪的是,如果我们在原始交付中添加额外的5个元素(有4个),我们最终会覆盖三个原始字段,然后另外创建第5个项目。所以我们最终会得到这样的结果:

[0] => Array
    (
        [stock] => 1
        [quantity] => 1
    )

[1] => Array
    (
        [stock] => 1
        [quantity] => 5
    )

[2] => Array
    (
        [stock] => 1
        [quantity] => 6
    )

[3] => Array
    (
        [stock] => 1
        [quantity] => 7
    )

[4] => Array
    (
        [stock] => 1
        [quantity] => 8
    )

[5] => Array
    (
        [stock] => 1
        [quantity] => 9
    )

我们关注Symfony v2.5.2和doctrine / orm v2.4.4

1 个答案:

答案 0 :(得分:1)

找到解决方案。我们的代码非常完美。问题在于phiamo/MopaBootstrapBundle处理的Issue #738(v3.0.0-beta 3)处理的实时表单生成。

我们用@wolfwolker和nrun options.initial_size = $this.parents(collection_id).find('.collection-items').children().length;评论的php app/console assetic:dump替换了第108行,现在一切正常。