Symfony2 - 如何在EventListeners中使用Data Transformer

时间:2015-11-18 20:36:57

标签: php symfony

  • 我需要使用事件监听器,因为我需要在表单中显示不同的内容,无论是新的还是已经存在的实体。我可以管理它。

  • 我需要一个Data Transformer,将实体显示为文本,这也是我可以做的事情。

=>但是,我无法同时执行2(数据转换器+事件监听器)。我收到错误: “错误:在非对象上调用成员函数add()”。如果我替换$ builder par $ form,我会收到以下错误:尝试调用类“Symfony \ Component \ Form \ Form”的名为“create”的未定义方法。

有效:

 $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
            //...
        }

这也有效:

$builder->add( $builder->create('element', 'text')->addModelTransformer($transformer));

但我不能让2同时工作。

    $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
            //...
        }
    });

2 个答案:

答案 0 :(得分:2)

我编写了一个表单扩展来支持这个用例而不改变字段类型。

1)创建扩展类。

#include <stdio.h>
#include <stdlib.h>

#define bucket_size 10

int find_the_largest(int arr[],int size);
void display(int arr[],int size);
void radix_sort(int arr[],int size);

int main()
{
    printf("------------------------------------------------------\n");
    printf("        Hey! This is a radix sort algorithm!\n");
    printf("------------------------------------------------------\n\n");
    int array[] = {10, 2, 303, 4021, 293, 1, 0, 429, 480, 92, 2999, 14};
    int size = sizeof(array)/sizeof(int);
    int largest_num = find_the_largest(array,size);
    printf("The unsorted array:");
    display(array,size);
    printf("The radix sort algorithm:\n\n");
    radix_sort(array,size);
    display(array,size);
    return 0;
}

int find_the_largest(int arr[],int size){
    int i,max_num=0;
    for(i=0;i<size;i++){
        if(arr[i]>max_num)
            max_num = arr[i];
    }
    return max_num;
}

void display(int arr[],int size){
    int i;
    for(i=0;i<size;i++){
        printf(" %d",arr[i]);
    if(i==size-1)
        printf("\n\n");
    }
}

void radix_sort(int arr[],int size){

    int semi_sort[12];
    int max_num = find_the_largest(arr,size);
    int i,significant_num = 1;

    while(max_num/significant_num>0){
        int bucket[bucket_size] = {0};

        for(i=0;i<size;i++){
            bucket[(arr[i]/significant_num)%10]++;
        }

        for(i=1;i<size;i++){
            bucket[i] += bucket[i-1];
        }

        for(i=size-1;i>=0;i--){

            semi_sort[--bucket[(arr[i]/significant_num)%10]] = arr[i];
        }


        for(i=0;i<size;i++)
            arr[i] = semi_sort[i];

        significant_num *= 10;
    }
}

2)将此扩展名注册为应用程序服务。

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));
    }
}

3)在构建表单时,为任何DataTransformer工具定义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 } 选项。

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() )); }); } 方法。

答案 1 :(得分:1)

简短回答:您无法在侦听器中添加变换器,因为表单已被锁定。

答案很长:有一些解决方案。最常见的,至少对我来说,是创建一个自定义表单类型,您可以在其中添加变换器。 然后添加自定义表单,通常在事件监听器中执行的操作:

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';
    }
}

将表单定义为服务:

 app.form.type.custom_element:
    class: AppBundle\Form\Type\ElementCustomType
    arguments: [@doctrine.orm.entity_manager]
    tags:
        - { name: form.type, alias: elementCustom }

像通常那样在听众中使用表单:

$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
        $element = $event->getData();
        $form = $event->getForm();
        $form->add('element', 'elementCustom')
    });