Symfony2 - 如何在FieldExtension中添加ModelTransformer?

时间:2014-10-12 15:04:13

标签: php forms validation symfony doctrine-orm

目标

自定义格式,写为Extension(Doctrine) Entity Field。元素呈现为Select2 Element with Tagging。这允许从列表中选择多个项目或添加新值。如果添加了新值,则应创建具有值作为属性的新实体,并将其与formType的基础模型相关联。

什么有效

我可以使用可用的实体成功渲染select2元素。

问题

提交的值是一个字符串,其中包含(唯一的)选定属性,这些属性当前会导致验证错误(无效值)。它没有像原始字段那样提供所选实体的ID,所以我写了一个应该能够处理它的generic DataTransformer。但是,我无法从TypeExtension 的上下文中attach the transformer to the field as intended。我必须在我的表单中添加变换器。我考虑的另一个选项是suppress the validation Listener enitrely,但这不仅会禁用enitre表单的验证,而且无法正确地将所选值映射到enitities。

实现此功能的最佳方法是什么?由于entity FieldType已经提供了大部分功能,我宁愿尽量避免编写一个完全新的fieldType。

更新:为什么我无法连接变压器

一个选项当然是按the cookbook entry建议的方式进行,即每当我使用该字段时附加变换器:

class MyFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ...

        $entityManager = $options['em'];
        $transformer = new ObjectListToStringTransformer($this->em,
                [
                    'class' => $options['class'],
                    'property' => $options['property'],
                    'delimiter' => ','
                ]
        );

        $builder->add(
            $builder->create('entityType', 'entity',
                array(
                    'select2' => true, /*Triggers the select2 template to be used*/
                    'multiple' => true,
                    'class' => 'Bundle:Entity',
                    'property' => 'name'
                )
            )->addModelTransformer($transformer)
        );
     }

     // ....
}

这可行。但这不是冗长而且不是类型安全的。如果我设置select2 => true,则必须添加Transformer ,否则将无法验证。所以我真的希望在我的扩展中完成这项工作。我实现这一目标的第一种方法就是错误,就像食谱条目中提到“如何不做”的方式一样:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    if ($options['select2']) {
        $builder->addModelTransformer(new ObjectListToStringTransformer($this->em,
                [
                    'class' => $options['class'],
                    'property' => $options['property'],
                    'delimiter' => ','
                ]
            )
        );
    }
    parent::buildForm($builder, $options);
}

这将为整个表单添加一个变换器,而不仅仅是这个字段。 AFAIK如果它是一个子类(垂直继承)但不在扩展(水平继承)内,我不能做create(...)->addModelTransformer($transformer)。在添加字段后是否有办法添加它?或者有没有办法通过创建选择字段的子类来实现这一目标?

1 个答案:

答案 0 :(得分:0)

显然,实体字段本身有一个已注册的ModelTransformer(或ViewTransformer),可在ModelTransformer之前调用。由于这总是失败,我的变压器永远不会到达。为了解决这个问题,我将addModelTransformer更改为addViewTransformer。虽然我的变压器的代码还没有工作,但与它的交互确实如此。