symfony表单提交不会将Request数组转换为Entity

时间:2016-04-01 08:24:29

标签: forms symfony

我尝试在其中创建一个带有嵌入形式的复杂表单。

表单需要同时创建/修改2个实体:InstrumentSpecification

在解释表单问题之前的一些重要信息:

这两个实体之间没有学说关系,因为Specification并不总是同一个类。例如,如果Instrument是吉他,则该类为GuitarSpecification,如果乐器是录音机,则该类为RecorderSpecification

Doctrine无法处理这种类型的关系,所以我手动管理它:

  • Instrument实体作为属性specification,具有关联的getter / setter
  • Specification实体在Instrument通过Doctrine Events的同时被加载,保留,删除。

Instrument的根表格是(简易版):

class InstrumentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->setRequestHandler(new JsonApiRequestHandler());

        $builder
            ->add('name',           TextType::class)
            // ... other fields
        ;

        // Add specification
        $formModifier = function(FormInterface $form, \InstrumentBundle\Entity\InstrumentType $instrumentType = null) {
            $prefix = null === $instrumentType ? 'Abstract' : $instrumentType->getPrefix();

            $form->add('specification', 'InstrumentBundle\\Form\\Specification\\' . $prefix . 'SpecificationType');
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($formModifier) {
                // Get Instrument Entity
                $data = $event->getData();

                $formModifier($event->getForm(), $data->getInstrumentType());
            }
        );

        $builder->get('instrumentType')->addEventListener(
            FormEvents::POST_SUBMIT,
            function(FormEvent $event) use ($formModifier) {
                // Get Instrument Entity
                $instrumentType = $event->getForm()->getData();

                $formModifier($event->getForm()->getParent(), $instrumentType);
            }
        );
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'csrf_protection' => false,
            'cascade_validation' => true,
            'data_class'      => 'InstrumentBundle\Entity\Instrument'
        ]);
    }
}

这种形式的孤独复杂性是有事件监听器(PRE_SET_DATAPOST_SUBMIT)检查Instrument(吉他,录音机等)的类型并添加正确的Specification表格(GuitarSpecification,RecorderSpecification等)。

以下是我的Specification表单类型之一的示例:

class GuitarSpecificationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('leftHanded',    CheckboxType::class)
            ->add('headstock',     TextType::class)
            ->add('body',          TextType::class)
            ->add('amplification', TextType::class)
            ->add('strings',       IntegerType::class)
            ->add('frets',         IntegerType::class)
            ->add('tuning')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'csrf_protection' => false,
            'data_class'      => 'InstrumentBundle\Entity\Specification\GuitarSpecification'
        ]);
    }
}

我的问题是提交表单时,Specification的Request数组部分未转换为实体,我收到错误:

Expected argument of type "InstrumentBundle\Entity\Specification\AbstractSpecification", "array" given

我无法找到解决这个问题的方法,所以欢迎任何想法。

1 个答案:

答案 0 :(得分:0)

只是一个问题,它不可能解决您的不同规范问题'使用Doctrine2的继承映射?

http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#inheritance-mapping