[英]Symfony2 - How to use a Data Transformer inside EventListeners
I need to use an Event Listener since I need different things to be displayed in my form whether it is new or an already existing entity. 我需要使用事件监听器,因为无论是新实体还是现有实体,我都需要在表单中显示不同的内容。 I can manage that. 我可以解决。
I need a Data Transformer, to display the entity as text, which is something I also can do. 我需要一个数据转换器,以将实体显示为文本,这也是我可以做的。
=> However, I fail in doing the 2 (Data Transformer+Event Listener) at the same time. =>但是,我无法同时执行2(Data Transformer + Event Listener)。 I get the error: "Error: Call to a member function add() on a non-object". 我收到错误:“错误:在非对象上调用成员函数add()”。 If I replace $builder par $form, I get the following error: Attempted to call an undefined method named "create" of class "Symfony\\Component\\Form\\Form". 如果我替换$ builder par $ form,则出现以下错误:尝试调用类“ Symfony \\ Component \\ Form \\ Form”的名为“ create”的未定义方法。
That works: 这样可行:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$element = $event->getData();
$form = $event->getForm();
if (!$element || null === $element->getId()) { //new entity
$form->add(...);
} else { //exist already
//...
}
That also works: 这也可以:
$builder->add( $builder->create('element', 'text')->addModelTransformer($transformer));
But I cannot make the 2 working at the same time. 但是我不能让两个同时工作。
$transformer = new ElementObjToStringTransformer($this->em);
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$element = $event->getData();
$form = $event->getForm();
if (!$element || null === $element->getId()) { //new entity
$builder->add( $builder->create('element', 'text')->addModelTransformer($transformer));
} else { //exist already
//...
}
});
I have wrote a Form Extension to support this use case without changing type of fields. 我编写了一个Form Extension以支持此用例,而无需更改字段类型。
1) Create extension class. 1)创建扩展类。
namespace AppBundle\Form\Extension\ModelTransformerExtension
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ModelTransformerExtension extends AbstractTypeExtension {
public function getExtendedType() {
return FormType::class;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
parent::buildForm($builder, $options);
if (isset($options['model_transformer'])) {
$builder->addModelTransformer($options['model_transformer']);
}
}
public function configureOptions(OptionsResolver $resolver) {
parent::configureOptions($resolver);
$resolver->setDefaults(array('model_transformer' => null));
}
}
2) Register this extension as an application service. 2)将此扩展注册为应用程序服务。
services:
app.form.extension.model_transformer:
class: AppBundle\Form\Extension\ModelTransformerExtension
tags:
- { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }
3) Define model_transformer
option to any DataTransformer implement when building the form. 3)在构建表单时,为任何DataTransformer实现定义model_transformer
选项。
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->addEventListener(FormEvents::PRE_SET_DATA, function ($event) {
$builder = $event->getForm();
$builder->add('myField', TextType::class, array(
'model_transformer' => new MyModelTransformer()
));
});
}
This idea can be extended to support addViewTransformer
method as well. 这个想法可以扩展为也支持addViewTransformer
方法。
Short answer: You can´t add the transformer inside the listener because the form is already locked. 简短的回答:您不能在监听器中添加转换器,因为该表单已被锁定。
Long answer: There are some solutions. 长答案:有一些解决方案。 The most common, at least for me, is to a create a Custom form type where you add your transformer. 至少对我来说,最常见的做法是创建一个“自定义”表单类型,在其中添加转换器。 Then you add your custom form how you would normally do in the event listener: 然后,您添加自定义表单,通常在事件侦听器中将执行以下操作:
class ElementCustomType extends AbstractType {
private $em;
public function __construct(EntityManager $entityManager)
{
$this->em = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->addModelTransformer(new ElementObjToStringTransformer($this->em))
;
}
public function getParent() {
return 'text';
}
public function getName() {
return 'elementCustom';
}
}
Define your form as a service: 将表单定义为服务:
app.form.type.custom_element:
class: AppBundle\Form\Type\ElementCustomType
arguments: [@doctrine.orm.entity_manager]
tags:
- { name: form.type, alias: elementCustom }
Use the form in the listener as your would normally do: 像通常那样在侦听器中使用表单:
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$element = $event->getData();
$form = $event->getForm();
$form->add('element', 'elementCustom')
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.