Symfony2字段的自定义句柄

时间:2015-11-25 11:23:02

标签: php forms symfony

我正在使用Symfony 2开发我的第一个复杂表单,但我已经卡住了。

This image represents my situation

所以,我有一个非常简单的实体,名为TShirt,具有以下属性:

  • 名称 - >映射为数据库中的字符串列
  • tags_data - >映射为数据库中的字符串列(将包含JSON对象)

然后我有一个包含比实体更多字段的表单:

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

我已阅读Data Transformers但据我所知,他们无法帮助我解决此问题,因为它们适用于映射字段。

给出这个场景,我想添加类似于数据变换器的东西,它采用颜色,大小和材质表单字段,并构建JSON对象以将其存储在实体中。

所以我的问题是:有没有办法自定义处理表单类中的非映射字段?

任何帮助都将非常感谢!谢谢!

3 个答案:

答案 0 :(得分:0)

也许您可以在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')
                 );

}

注意FormEvents(此处:PRE_SET_DATA)。

此外,$data = $event->getData();允许您获取相关对象。你可以在它上面循环并解析JSON (或创建尽可能多的JSON数组包含的方法并反复调用它们),以便显示尽可能多的$form->add(..。 JSON数组。

答案 1 :(得分:0)

将它存储在tagsData中不是一个好方法!

SYMFONY 2.7的解决方案

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

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

答案 2 :(得分:0)

我终于通过创建自定义DataMapper来解决问题,正如本教程所解释的那样 https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/