删除来自空集合表单项的空值

时间:2013-07-15 11:33:57

标签: forms symfony collections null

我正在尝试在2个实体之间的表单中实现ManyToMany关系(例如,Product and Category to make simpe)并使用docs中描述的方法使用prototype和javascript(http://symfony.com/doc/current/cookbook/form/form_collections.html)。

以下是ProductType中创建类别集合的行:

$builder->add('categories', 'collection', array(
                   'type' => 'entity',
                   'options' => array(
                        'class' => 'AppBundle:Category',
                        'property'=>'name',
                        'empty_value' => 'Select a category',
                        'required' => false),
                   'allow_add' => true,
                   'allow_delete' => true,
              ));

当我有一个新项目时,新的选择显示设置为空值“选择一个类别”。问题是,如果我不更改空值,则将其发送到服务器,并在$ form-> bind()后,我的Product对象在$ category ArrayCollection中获取一些空值。

我首先测试Product实体中setter中的值,并在ProductType中添加'by_reference'=> false,但在这种情况下,我得到一个异常,声明null不是Category的实例。

如何确保忽略空值?

3 个答案:

答案 0 :(得分:8)

引用documentation' delete_empty':

  

如果要从表单中显式删除完全空的集合条目,则必须将此选项设置为true

$builder->add('categories', 'collection', array(
               'type' => 'entity',
               'options' => array(
                    'class' => 'AppBundle:Category',
                    'property'=>'name',
                    'empty_value' => 'Select a category'),
               'allow_add' => true,
               'allow_delete' => true,
               'delete_empty' => true
          ));

由于您使用的是嵌入式表单,因此在传递空集合时可能会遇到Warning: spl_object_hash() expects parameter 1 to be object, null given等问题。

按照此answer的说明删除required=>false对我不起作用。

类似的问题在github上被引用here并由PR 9773解析

答案 1 :(得分:7)

我终于找到了一种方法来处理事件监听器。 这个discussion给出了所有FormEvents的含义。 在这种情况下,PRE_BIND(由2.1及更高版本中的PRE_SUBMIT替换)将允许我们在绑定到实体之前修改数据。

查看Symfony源代码中Form的实现是我发现如何使用这些事件的唯一信息来源。对于PRE_BIND,我们看到表单数据将由事件数据更新,因此我们可以使用$event->setData(...)对其进行更改。以下代码段将遍历数据,取消设置所有空值并将其设置回来。

$builder->addEventListener(FormEvents::PRE_BIND, function(FormEvent $event){
    $data = $event->getData();
    if(isset($data["categories"])) {
        foreach($data as $key=>$value) {
            if(!isset($value) || $value == "")
                unset($data[$key]);
        }
        $event->setData($data);
});

希望这可以帮助别人!

答案 2 :(得分:0)

自Symfony 3.4起,您可以将闭包传递给delete_empty

$builder
    ->add('authors', CollectionType::class, [
        'delete_empty' => function ($author) {
            return empty($author['firstName']);
        },
    ]);

https://github.com/symfony/symfony/commit/c0d99d13c023f9a5c87338581c2a4a674b78f85f