我们遵循acmepizzabundance提供的示例。我们有一个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的Delivery时,一切似乎都可以正常工作。这是由于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
)
)
)
更奇怪的是,如果我们在原来的Delivery中添加额外的5个元素(4个),我们最终会覆盖原来的3个字段,然后额外创建第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
找到解决方案。我们的代码工作得很完美。问题是由phiamo/MopaBootstrapBundle (v3.0.0-beta 3)处理的实时表单生成,如问题#738所指出的。
因此,我们用@wolfwolker注释的options.initial_size = $this.parents(collection_id).find('.collection-items').children().length;
和nrun php app/console assetic:dump
替换了第108行,现在一切正常。