我有一个实体,它位于三个一对一映射的反面。实体 FittingStep
由 FittingStepSingleValue
等映射。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/