Symfony 2中的ArrayCollection(表单集合)索引冲突

时间:2015-06-27 16:21:36

标签: javascript php forms symfony collections

我正在使用Symfony2来构建我的页面。 当我尝试更新表单集合时(如cookbook条目" How to Embed a Collection of Forms")中所述,我得到前端索引和后端ArrayCollection索引的冲突

我已经获得了User< - >的关系地址(OneToMany)。用户想要创建/更新/删除他的地址,因此他可以在javascript部分新地址元素的帮助下在前端添加/删除。他做了以下事情:

(1)添加新地址(索引:0)

(2)添加新地址(索引:1)并立即再次删除该地址

(3)添加新地址(索引:2)。

当他点击“保存”按钮时,以下代码会保存/更新用户(及其地址):

 $this->em->persist($user);
 $this->em->flush();

然后将新地址正确地保存到数据库中。 现在用户想要更新地址,例如索引为0。 当他现在点击保存按钮时,它会使用"索引0"更新地址,但同时,它会再次添加"索引2"到数据库(对象)。 为了更好地理解这个问题,我画了一个小插图(手工制作,对我糟糕的艺术技巧感到抱歉):

Collection error image 现在,我的地址是"索引1"在我的对象/数据库中。 我知道为什么会发生这种情况,因为第一个"索引1" address被映射到ArrayCollection元素" number 1",第二个被映射到" number 2"(因为前端名称"索引2")。 您可以说:"它只是填满地址,直到它到达后端的前端索引" .. 但是我该如何解决这个问题呢?

网站说明: 使用ajax请求会发生此行为,因为如果您在单击"保存按钮"后重新加载页面,它将使用后端中的索引正确地重新索引前端中的地址。

我建议处理这种情况:

单击服务器端保存后重新索引前端索引 索引。这是我的问题的明确/唯一解决方案吗?

3 个答案:

答案 0 :(得分:7)

是的,这是Symfony表单集合的问题,它没有简单的解决方案imho。但是我不得不问你为什么不对页面刷新做同样的事情呢?您只能刷新带有集合的html代码段。代码段的HTML代码可以来自服务器端。回到你的问题 - 是的,重新索引是一个很好的解决方案,直到你不想尝试自己编写自定义集合类型。

symfony/symfony/issues/7828

在集合中验证存在类似的问题 - symfony/symfony/issues/7468

我认为默认集合类型和Symfony文档中的教程有一些缺点。希望有帮助。

答案 1 :(得分:2)

我通过修改Symfony文档中给出的Javascript / Jquery代码来解决客户端问题。

不是通过计算子元素对新元素进行编号,而是查看最后一个元素的id并使用正则表达式提取其索引。

添加元素时,我将最后一个索引递增1.这样,我从不使用相同的索引。

这是我的代码:

// Initializing default index at 0
var index = 0;

// Looking for collection fields in the form
var $findinput = $container.find(':input');

// If fields found then looking for last existing index
if ( $findinput.length > 0 ) {

    // Reading id of last field
    var myString = $findinput.last().attr('id')

    // Setting regular expression to extract number from id containing letters, hyphens and underscores
    var myRegex = /^[-_A-Za-z]+([0-9]+)[-_A-Za-z]*$/

    // Executing regular expression on last collection field id
    var test = myRegex.exec(myString);

    // Extracting last index and incrementing by 1
    if (test.length > 0) index = parseInt(test[1]) + 1;
}

答案 2 :(得分:1)

在过去的两年里,我曾多次遇到过这个问题。通常,按照Symfony教程How to Embed a Collection of Forms完成工作就好了。你需要做一些javascript编码来添加"编辑/更新"功能,但除此之外 - 使用这种方法你应该没问题。

另一方面,如果你有一个非常复杂的形式,使用AJAX验证/保存/计算/业务逻辑/等,我发现它通常更好将最终数据存储到会话中的数组中。提交表单后,在if($form->isValid()){...}块内,您将有

$collection = new ArrayCollection($mySessionPlainArray);
$user->setAddress($collection);

我想警告您要小心数据的序列化 - 如果您正在使用实体,可能会遇到一些尴尬的例外或不当行为(请参阅我的question )。

抱歉,我无法提供更多代码,但此问题的解决方案有时非常复杂。