简体   繁体   English

Symfony2自定义字段句柄

[英]Symfony2 custom handle of fields

I am developing my first complex form with Symfony 2 and I have gotten stuck. 我正在用Symfony 2开发我的第一个复杂表格 ,但是我陷入了困境。

This image represents my situation 此图代表我的情况

So, I have a very simple entity called TShirt with the following attributes: 因此,我有一个非常简单的实体TShirt,它具有以下属性:

  • name -> mapped as a string column in the database 名称->映射为数据库中的字符串列
  • tags_data -> mapped as a string column in the database (that will contain a JSON object) tags_data->映射为数据库中的字符串列(将包含JSON对象)

Then I have a form with more fields than the entity has: 然后,我有一个表单,其中包含比实体更多的字段:

class TShirtType extends AbstractType {

    public function buildForm( FormBuilderInterface $builder, array $options ) {

        $builder
            ->add('name', 'text', array(
                'required' => true,
            ))
            ->add( 'colours', 'choice', array(
                'choices' => $availableColours,
                'multiple' => true,
                'expanded' => true,
                'mapped' => false,
            ))
            ->add( 'sizes', 'choice', array(
                'choices' => $availableSizes,
                'multiple' => true,
                'expanded' => true,
                'mapped' => false,
            ))
            ->add( 'materials', 'choice', array(
                'choices' => $availableMaterials,
                'multiple' => true,
                'expanded' => true,
                'mapped' => false,
            ));
    }

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions( OptionsResolverInterface $resolver ) {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TShirt',
        ));
    }


    public function getName() {
        return 'app_bundle_tshirt_form';
    }
}

I have read about Data Transformers but as far as I know they cannot help me in this issue because they work with mapped fields. 我已经阅读了有关Data Transformers的信息,但据我所知,由于它们与映射的字段一起使用,因此它们无法在此问题上为我提供帮助。

Giving this scenario, I want to add something like the Data Transformers that takes the colours, sizes and materials form fields and builds the JSON object to store it in the Entity. 考虑到这种情况,我想添加诸如Data Transformers之类的东西,它采用颜色,大小和材料形式的字段,并构建JSON对象以将其存储在Entity中。

So my question is: Is there a way for custom handling the non-mapped fields in the form class? 所以我的问题是: 有没有一种方法可以自定义处理表单类中的非映射字段?

Any help would be very appreciated! 任何帮助将不胜感激! Thanks!! 谢谢!!

Maybe you could use an EventListener in your FormType like below : 也许您可以在FormType中使用EventListener,如下所示:

    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $formFactory = $builder->getFormFactory();
        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (\Symfony\Component\Form\FormEvent $event) use ($formFactory, $builder) {
                $data = $event->getData();
                $form->add(
                    'customFieldName',
                     'text',
                      array('some_options' => 'someOptionValue')
                 );

}

Be careful about FormEvents (here : PRE_SET_DATA). 请注意FormEvents(此处:PRE_SET_DATA)。

Also, $data = $event->getData(); 另外, $data = $event->getData(); allows you to get the related object. 允许您获取相关对象。 You could loop on it and parse JSON (or create as much method as your JSON array contains and call them over and over) in order to display as much $form->add(.. as you have properties ion you JSON array. 您可以对其进行循环并解析JSON (或创建与JSON数组包含的方法一样的方法,并反复调用它们) ,以便显示尽可能多的$form->add(..因为您具有JSON数组的属性。

it's not good solution to store it in tagsData ! 将其存储在tagsData中不是一个好的解决方案!

solution for SYMFONY 2.7 SYMFONY 2.7的解决方案

Controller.php: Controller.php这样:

$colors = [
    'white' => 'white',
    'black' => 'black',
    'green' => 'green'
];
$sizes = [
    'M' => 'M',
    'L' => 'L',
    'XL' => 'XL'
];
$materials = [
    'Cotton' => 'Cotton',
    'Wool' => 'Wool',
    'Silk' => 'Silk'
];

$object = new TShirt();
$form = $this->createForm(new TShirtType(), $object, ['colours' => $colors, 'sizes' => $sizes, 'materials' => $materials]);
$form->handleRequest($request);

TShirtType.php TShirtType.php

class TShirtType extends AbstractResourceType
{

    public function buildForm( FormBuilderInterface $builder, array $options ) {

        $builder
            ->add('name', 'text', array(
                'required' => true,
            ))
            ->add( 'colours', 'choice', array(
                'choices' => $options['colours'],
                'multiple' => true,
                'expanded' => true,
                'mapped' => false
            ))
            ->add( 'sizes', 'choice', array(
                'choices' => $options['sizes'],
                'multiple' => true,
                'expanded' => true,
                'mapped' => false
            ))
            ->add( 'materials', 'choice', array(
                'choices' => $options['materials'],
                'multiple' => true,
                'expanded' => true,
                'mapped' => false
            ));

            $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event)
            {
                $object = $event->getData();
                $form = $event->getForm();

                $tagsData = [
                    'colours' => $form->get('colours')->getData(),
                    'sizes' => $form->get('sizes')->getData(),
                    'materials' => $form->get('materials')->getData(),
                ];
                $object->setTagsData($tagsData);

                $event->setData($object);
            });
    }

    public function finishView(FormView $view, FormInterface $form, array $options)
    {
        $tagsData = $view->vars['data']->getTagsData();

        if($tagsData) {
            $types = ['colours', 'sizes', 'materials'];
            foreach($types as $type) {
                foreach($view->offsetGet($type) as $checkbox) {
                    $checkbox->vars['checked'] = isset($tagsData[$type]) && in_array($checkbox->vars['value'], $tagsData[$type]);
                }
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver ) {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\TShirShirt',
        ));
        $resolver->setRequired(['colours', 'sizes', 'materials']);
    }

    public function getName() {
        return 'app_bundle_tshirt_form';
    }
}

我最终通过创建自定义DataMapper解决了该问题,因为本教程说明了https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM