Symfony2(> = 2.3):如何听孩子的父表格事件?

Osk*_*kar 5 forms events symfony

我有一个自定义FormType,当父表单持续存在时,需要将其自身添加到父实体.

在Symfony <2.3中,可以通过执行以下操作来完成:

class FooType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        ...
        $builder->getParent()->addEventSubscriber(new FooSubscriber)
    }
}

class FooSubscriber implements EventSubscriberInterface
{
    static function getSubscribedEvents()
    {
        return array(
            FormEvents::POST_SUBMIT => 'postSubmit'
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

但升级到Symfony 2.6之后,我发现$builder->getParent()已经删除了.但现在我无法听取提交的父母的意见.

所以我将监听器添加到我的构建器并从订阅服务器中引用了父级.但这并没有真正起作用,因为我检查父表单是否有效 - 它不是,因为它还没有提交:

function postSubmit(FormEvent $e)
{
    if ($e->getForm()->getParent()->getRoot()->isValid()) {
        //this gives 'false'
Run Code Online (Sandbox Code Playgroud)

这个错误是由下一段代码引起的:

// Symfony\Component\Form\Form.php @ line 744
public function isValid()
{
    if (!$this->submitted) {
        return false;
    }
Run Code Online (Sandbox Code Playgroud)

并且因为父表单首先遍历所有子节点并提交,所以在设置之前$this->submitted = true...我不确定父节点是否有效.


TL; DR

如何将Eventlistener添加到我的父表单,而无需调整我的父表单?我希望我的FooType能够添加到所有表单中,而不必知道/记住为特定的FooType做一些逻辑.

Bar*_*art 0

我需要相同的功能,因为我有一个自定义表单字段,在更新所有映射字段后需要父实体。不幸的是,子表单的 POST_SUBMIT 在父表单上的 SUBMIT 运行之前被调用。

我最终将 eventDispatcher 传递给了孩子,并将我的监听器绑在那里。我需要两个侦听器来完成工作:一个用于获取处理后的值,另一个用于更新主实体。通过引用将 $ generatedPassword 传递给闭包,您可以将数据从子事件共享到父事件。

#Parent::buildForm

$builder->add('generate_password', GeneratePasswordType::class, [
    'event_dispatcher' => $builder->getEventDispatcher(),
]);
Run Code Online (Sandbox Code Playgroud)

#Child::buildForm

// first listen to submit event to get current field value
$generateNewPassword = false;
$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use (&generateNewPassword) {
    $generateNewPassword = null !== $event->getData();
});

// then run updater after parent entity has been updated
$parentDispatcher = $options['event_dispatcher'];
$parentDispatcher->addListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use (&$generateNewPassword) {
    $user = $event->getData();
    if(true === $generateNewPassword){
        // update password & email user new credentials
    }
}
Run Code Online (Sandbox Code Playgroud)

(自定义字段是用户管理模块的标记为“保存时生成新密码”的复选框。它通过电子邮件向用户发送生成的密码,这就是为什么我需要来自主实体的最新电子邮件地址)