php - 无法将现有实体映射到 symfony2 中的嵌入形式

标签 php forms symfony symfony-2.2

我有一个实体,它位于三个一对一映射的反面。实体 FittingStepFittingStepSingleValue 等映射。FittingStep 有一个字段 fittingStepType 标识三个实体中的哪一个FittingStep 应该查找。我想将该对象嵌入到 FittingStep 编辑表单中。

我已将表单定义为每个子表单的服务:

services:
    ihear.form.fitting_step_single_value:
        class: Ihear\FittingBundle\Form\FittingStepSingleValueType
        arguments: [@security.context]
        tags:
            -   
                name: form.type
                alias: ihear_fittingbundle_fittingstepsinglevaluetype
    ihear.form.fitting_step_double_value:
        class: Ihear\FittingBundle\Form\FittingStepDoubleValueType
        arguments: [@security.context]
        tags:
            -   
                name: form.type
                alias: ihear_fittingbundle_fittingstepdoublevaluetype
    ihear.form.fitting_step_option:
        class: Ihear\FittingBundle\Form\FittingStepOptionType
        arguments: [@security.context]
        tags:
            -   
                name: form.type
                alias: ihear_fittingbundle_fittingstepoptiontype

这些服务类看起来像这样(非常基本)

class FittingStepSingleValueType extends AbstractType
{
    private $securityContext;

    public function __construct(SecurityContext $securityContext)
    {   
        $this->securityContext = $securityContext;
    }   

    public function buildForm(FormBuilderInterface $builder, array $options)
    {   
        $builder
            ->add('max1')
            ->add('description1')
            ->add('fittingStep', 'hidden')
        ;   
    }   

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Ihear\FittingBundle\Entity\FittingStepSingleValue'
        ));
    }

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

我的表单使用 PRE_SET_DATA 上的 EventListener 来添加适当的嵌入式表单字段:

class FittingStepType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {   
        $builder
            ->add('name')
            ->add('abbreviation')
            ->add('description')
            ->add('fittingStepType',
                'choice',
                ['choices' => ['SingleValue' => 'SingleValue',
                               'DoubleValue' => 'DoubleValue',
                               'Option' => 'Option'],
                 'empty_value' => 'select one please'])
        ;   

        $formModifier = function(FormInterface $form, $fittingStepType) {
            switch ($fittingStepType) {
                case 'SingleValue':
                    $form->add('fittingStepSingleValue',
                        'ihear_fittingbundle_fittingstepsinglevaluetype');
                    if ($form->has('fittingStepDoubleValue'))
                        $form->remove('fittingStepDoubleValue');
                    if ($form->has('fittingStepOption'))
                        $form->remove('fittingStepOption');
                    break;
                case 'DoubleValue':
                    $form->add('fittingStepDoubleValue',
                        'ihear_fittingbundle_fittingstepdoublevaluetype');
                    if ($form->has('fittingStepSingleValue'))
                        $form->remove('fittingStepSingleValue');
                    if ($form->has('fittingStepOption'))
                        $form->remove('fittingStepOption');
                    break;
                case 'Option':
                    $form->add('fittingStepOption',
                        'ihear_fittingbundle_fittingstepoptiontype');
                    if ($form->has('fittingStepSingleValue'))
                        $form->remove('fittingStepSingleValue');
                    if ($form->has('fittingStepDoubleValue'))
                        $form->remove('fittingStepDoubleValue');
                    break;
            }
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($formModifier) {
                $form = $event->getForm();
                // this is the FittingStep
                $data = $event->getData();
                // this is the Entity that contains the value(s)
                // i.e. FittingStepSingleValue
                $fittingStepType = $data->getFittingStepType();
                switch ($fittingStepType) {
                    case 'SingleValue':
                        $formModifier($form, $fittingStepType);
                        break;
                    case 'DoubleValue':
                        $formModifier($form, $fittingStepType);
                        break;
                    case 'Option':
                        $formModifier($form, $fittingStepType);
                        break;
                }
            }
        );
    }
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Ihear\FittingBundle\Entity\FittingStep'
        ));
    }

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

我的编辑操作 Controller :

/** 
 * Displays a form to edit an existing FittingStep entity.
 *
 * @Route("/{id}/edit", name="admin_fittingstep_edit")
 * @Method("GET")
 * @Template()
 */
public function editAction($id)
{   
    $em = $this->getDoctrine()->getManager();

    $entity = $em->getRepository('IhearFittingBundle:FittingStep')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException(
            'Unable to find FittingStep entity.');
    }   

    $editForm = $this->createForm(new FittingStepType(), $entity);
    $deleteForm = $this->createDeleteForm($id);

    return array(
        'entity'      => $entity,
        'edit_form'   => $editForm->createView(),
        'delete_form' => $deleteForm->createView(),
    );  
}   

当我尝试加载表单时,出现异常:

The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class Ihear\FittingBundle\Entity\FittingStep. You can avoid this error by setting the "data_class" option to "Ihear\FittingBundle\Entity\FittingStep" or by adding a view transformer that transforms an instance of class Ihear\FittingBundle\Entity\FittingStep to scalar, array or an instance of \ArrayAccess.

我做错了什么?似乎实体之间的对象映射与表单上的映射之间存在某种脱节。作为旁注,我在我的创建表单中成功使用了 $formModifier 闭包,因此在使用嵌入表单创建新实体时它工作正常。

最佳答案

您必须将 fittinStep 从 hidden 更新为 Collection

->add('fittingStep', 'hidden')

收款文件:http://symfony.com/doc/current/reference/forms/types/collection.html

->add('fittingStep', 'collection', array('type'=>new FittingStepType(), 'label'=>false))

关于php - 无法将现有实体映射到 symfony2 中的嵌入形式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20210871/

相关文章:

php - 动态生成表clospan表头

jquery - 如何在动态元素上使用preventDefault?

javascript - 使用 jquery 提交表单时指出表单中的特定错误位置

php - Money\Money 无法转换为字符串

php - 为什么我必须使用 PDO 启动事务,然后提交它才能从 MySQL DB 中删除数据

javascript - 通用ajax表单提交

symfony - 在 bundle 之间管理/共享通用翻译字符串的最佳方式

symfony - 修改消费者内部rabbitMQ发送的消息

javascript - 使用 Javascript 将复选框动态添加到 Symfony 2 表单

php - 有没有办法通过在正文中使用 PHP 来覆盖页面的 <title> 标记?