mat*_*exx 6 php forms symfony symfony-2.2
我有一个实体,它与三个一对一映射相反.实体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
Run Code Online (Sandbox Code Playgroud)
这些服务类看起来像这样(非常基本)
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';
}
}
Run Code Online (Sandbox Code Playgroud)
我的表单在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';
}
}
Run Code Online (Sandbox Code Playgroud)
我的控制器用于编辑操作:
/**
* 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(),
);
}
Run Code Online (Sandbox Code Playgroud)
当我尝试加载表单时,我得到一个例外:
表单的视图数据应该是标量,数组或\ ArrayAccess的实例,但是类Ihear\FittingBundle\Entity\FittingStep的实例.您可以通过将"data_class"选项设置为"Ihear\FittingBundle\Entity\FittingStep"或添加视图转换器来将此类错误设置为"Ihear\FittingBundle\Entity\FittingStep"转换为标量,数组或\的实例ArrayAccess接口.
我究竟做错了什么?似乎实体之间的对象映射与表单上的映射之间存在某种脱节.作为旁注,我$formModifier在创建表单中成功使用了闭包,因此在使用嵌入表单创建新实体时它可以正常工作.
我解决了这个问题。实体之间的关系由嵌入实体引用,因此我在嵌入表单中添加了父实体的隐藏字段。这个小流氓并没有给创建表单带来任何麻烦,但是当我嵌入表单来编辑现有实体时却导致了上面的错误。感谢@albert 向我指出了那行代码!
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')
// this line was the culprit
//->add('fittingStep', 'hidden')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ihear\FittingBundle\Entity\FittingStepSingleValue'
));
}
public function getName()
{
return 'ihear_fittingbundle_fittingstepsinglevaluetype';
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
938 次 |
| 最近记录: |