Symfony2 形成事件和模型转换器
我正在纠结,试图与Symfony2的表单构建器,事件和变形金刚摔跤......希望这里有人更有经验,可以帮忙!
我有一个表单字段(选择下拉列表),其中包含一些映射到实体的值(候选列表)。其中一个选项是“其他”。假设目前没有AJAX,当用户提交表单时,我想检测他们是否选择了“其他”(或不在候选列表中的任何其他选项)。如果他们选择了这些选项之一,则应显示完整的选项列表,否则只需显示候选列表。应该很容易,对吧?;)
所以,我有我的表单类型,它显示基本的候选名单就好了。代码如下所示:
namespace Company\ProjectBundle\Form\Type;
use ...
class FancyFormType extends AbstractType {
private $fooRepo;
public function __construct(EntityManager $em, FooRepository $fooRepo)
{
$this->fooRepo = $fooRepo;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
/** @var Bar $bar */
$bar = $builder->getData();
$fooTransformer = new FooToStringTransformer($options['em']);
$builder
->add($builder
->create('linkedFoo', 'choice', array(
'choices' => $this->fooRepo->getListAsArray(
$bar->getLinkedfoo()->getId()
),
))
->addModelTransformer($fooTransformer)
)
;
// ...
}
// ...
}
现在,我想检查提交的值,以便按如下方式使用表单事件侦听器。
public function buildForm(FormBuilderInterface $builder, array $options) {
// ... This code comes just after the snippet shown above
$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
/** @var EntityManager $em */
$em = $event->getForm()->getConfig()->getOption('em');
$data = $event->getData();
if (empty($data['linkedFoo'])) return;
$selectedFoo = $data['linkedfoo'];
$event->getForm()->add('linkedFoo', 'choice', array(
'choices' => $em
->getRepository('CompanyProjectBundle:FooShortlist')
->getListAsArray($selectedFoo)
,
));
//@todo - needs transformer?
});
}
但是,它会失败,并显示如下错误消息:
Notice: Object of class Proxies\__CG__\Company\ProjectBundle\Entity\Foo could not be converted to int in \path\to\project\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php line 458
我推测这个错误是因为当被覆盖时,它删除了?我在事件关闭时尝试了各种方法来访问构建器,但这似乎不起作用(返回值是意外的)。除了?还是我在这里的方法有更根本的问题?linkedFoo
modelTransformer
$event->getForm()->add()
基本上,我不想弄乱字段的配置/转换器/标签,除了更改可用的选择...有没有其他方法可以做到这一点?例如,类似 ?linkedFoo
$form->getField()->updateChoices()
提前感谢您提供的任何帮助!
C
附言:有没有比Symfony网站上更好的表格,事件等文档或讨论?例如,PRE_SET_DATA、PRE_SUBMIT、SUBMIT 等之间的区别是什么?他们什么时候被解雇?它们应该用于什么?继承如何与自定义表单域一起使用?什么是表单和构建器,它们如何交互以及何时应处理它们?如何,何时以及为什么应该使用可以通过访问的FormFactory?等。。$form->getConfig()->getFormFactory()
编辑:为了回应Florian的建议,这里有一些关于尝试但不起作用的事情的更多信息:
如果您尝试在事件中获取表单生成器,如下所示:
/** @var FormBuilder $builder */
$builder = $event->getForm()->get('linkedFoo')->getConfig();
$event->getForm()->add($builder
->create('linkedFoo', 'choice', array(
'choices' => $newChoices,
'label' =>'label',
))
->addModelTransformer(new FooToStringTransformer($em))
);
然后你得到错误:
FormBuilder methods cannot be accessed anymore once the builder is turned
into a FormConfigInterface instance.
然后你尝试像Florian建议的那样,即
$event->getForm()->add('linkedFoo', 'choice', array(
'choices' => $newChoices,
));
$event->getForm()->get('linkedFoo')->getConfig()->addModelTransformer(new FooToStringTransformer($em));
...但是您会收到此错误:
Notice: Object of class Proxies\__CG__\Company\ProjectBundle\Entity\Foo could not be converted to int
in C:\path\to\vendor\symfony\symfony\src\Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList.php line 458
这似乎表明第二行(添加 ModelTransformer)永远不会被调用,因为在你到达那里之前调用失败。->add()