2

我正在尝试以 2 个实体(例如 Product 和 Category 以制作 simpe)之间的形式实现 ManyToMany 关系,并使用带有原型和 javascript 的文档中描述的方法(http://symfony.com/doc/current/食谱/表格/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 的实例。

如何确保忽略空值?

4

3 回答 3

8

Citing the documentation on 'delete_empty':

If you want to explicitly remove entirely empty collection entries from your form you have to set this option to 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
          ));

Since you use embedded forms, you could run in some issues such as Warning: spl_object_hash() expects parameter 1 to be object, null given when passing empty collections.

Removing required=>false as explained on this answer did not work for me.

A similar issue is referenced here on github and resolved by the PR 9773

于 2015-01-18T12:50:41.860 回答
7

我终于找到了一种使用事件侦听器来处理它的方法。这个讨论给出了所有 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);
});

希望这可以帮助别人!

于 2013-07-16T07:55:36.083 回答
1

从 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

于 2019-02-27T12:30:12.427 回答