我有一个名为HoursSpecial的实体,它与一个名为HoursArea的实体具有外键关系。每个HoursSpecial属于HoursArea。当我通过我的HoursSpecialType创建一个新的HoursSpecial时,我希望表单字段自动填充HoursArea字段。
我知道你在想什么,只是在我的控制器方法中做这样的事情:
$form->add('area', 'hidden', array('data'=>$area));
除非我需要让DataTransformer在区域ID和实际区域实体之间切换,否则这样会很好。所以我必须使用变换器在HoursSpecialType中声明我的HoursArea字段:
$builder
...
->add('area', 'hidden')
;
$builder->get('area')->addModelTransformer(new HoursAreaToIntTransformer($this->manager));
现在,我无法简单地将HoursArea实体提供给表单。有没有一种有效的方法来实现这一目标?
我已经在How to Dynamically Modify Forms Using Form Events上翻阅了Symfony的文档,但是我无法从表单构建器外部动态传递那个HoursArea实体。 。也许我只是错过了一些东西?
更新
根据以下@Ryan的答案(建议#1)的建议,我创建了自定义类型HiddenHoursAreaType:
// AppBundle\Form\Type\HideenHoursAreaType.php
class HiddenHoursAreaType extends AbstractType
{
//need to instantiate HoursAreaToIntTransformer
private $manager;
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new HoursAreaToIntTransformer($this->manager);
$builder->addModelTransformer($transformer);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
'compound' => true //this should be FALSE as there are no children
));
}
/**
*
* the return value of the getParent function indicates that you're extending the choice field type.
* This means that, by default, you inherit all of the logic and rendering of that field type.
*/
public function getParent()
{
return 'hidden';
}
public function getName()
{
return 'app_hoursArea';
}
我已将变换器添加到自定义类型类中。这是变压器类:
// AppBundle\Form\DataTransformer;
class HoursAreaToIntTransformer implements DataTransformerInterface
{
private $manager;
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
}
/**
* Transforms an object (HoursArea) to a string (number).
*
* @param Issue|null $issue
* @return string
*/
public function transform($area)
{
if (null === $area) {
return '';
}
return $area->getId();
}
/**
* Transforms a string (number) to an object (HoursArea).
*
* @param string $areaId
* @return HoursArea|null
* @throws TransformationFailedException if object (HoursArea) is not found.
*/
public function reverseTransform($areaId)
{
// no area number? It's optional, so that's ok
if (!$areaId) {
return;
}
$area = $this->manager
->getRepository('AppBundle:HoursArea')
// query for the issue with this id
->find($areaId)
;
if (null === $area) {
// causes a validation error
// this message is not shown to the user
// see the invalid_message option
throw new TransformationFailedException(sprintf(
'An area with number "%s" does not exist!',
$areaId
));
}
return $area;
}
}
在我的控制器中,我使用自定义类型字段创建表单:
$form = $this->createForm(new HoursSpecialType($this->getDoctrine()->getManager()), $entity, array(
'action' => $this->generateUrl('hoursspecial_postcreate'),
'method' => 'POST',
));
$form->add('eventDate', 'hidden', array('data'=>$dateString));
$form->add('area', new \AppBundle\Form\Type\HiddenHoursAreaType($this->getDoctrine()->getManager()), array(
'data'=>$area,
'invalid_message'=>'Area field not converted proerly'
));
$form->add('submit', 'submit', array('label' => 'Create'));
由于变换器和自定义类型,表单现在可以正确地将HoursArea实体转换为隐藏字段中填充的整数。
现在的问题是,在表单提交时,整数不会转换回HoursArea对象。我知道这是因为我得到了' invalid_message'提交后。
最终更新
未正确插入HoursArea ID的原因与
有关'compound' => true
我的自定义类型设置。我认为它正在寻找儿童田地,并没有找到任何......它不应该没有,因为没有!
答案 0 :(得分:2)
您可以为其创建自定义类型,并在自定义类型的addModelTransformer()
中添加buildForm()
调用,但仍会显式传递数据。因此,$form->add('area', 'hidden', array('data'=>$area))
将成为$form->add('area', new HiddenHoursAreaType(), array('data'=>$area))
,其中HiddenHoursAreaType::getParent()
将是hidden
类型。
您可以在POST_SET_DATA
监听器中设置数据。
您可以在$options['data']
中获取buildForm()
值并明确传入HoursArea
ID。
/** @var HoursSpecial $hoursSpecial Prepopulated in controller */
$hoursSpecial = $options['data']
$builder->add('area', 'hidden', ['data' => $hoursSpecial->getHoursArea()->getId()])