订阅者拨打两次symfony

时间:2018-06-12 20:26:50

标签: symfony

我在提交表单后使用FOSUserEvents但订阅者调用了两次。

这样我的验证码第一次有效而第二次无效

这是我的代码

<?php

namespace AppBundle\EventListener;



class CaptchaSubscriber implements EventSubscriberInterface
{

    private $router;
    private $requestStack;
    private $templating;

    /**
     * RedirectAfterRegistrationSubscriber constructor.
     */
    public function __construct(RouterInterface $router, RequestStack $requestStack, \Twig_Environment $templating)
    {
        $this->router = $router;
        $this->requestStack = $requestStack;
        $this->templating = $templating;

    }

    public function onRegistrationInit(GetResponseUserEvent $event)
    {

        if ($this->requestStack->getMasterRequest()->isMethod('post')) {

            ...handle captcha...

        }

    }

    public static function getSubscribedEvents()
    {
        return [
            FOSUserEvents::REGISTRATION_INITIALIZE => 'onRegistrationInit'
        ];
    }        
}

我的symfony是3.3

更新

我添加了

        $event->stopPropagation();

使用此代码片段代码可以正常工作,但我不知道这是否是最佳实践

2 个答案:

答案 0 :(得分:1)

如果您使用的是自动装配/自动配置,则可能已经添加了上面显示的订户服务两次。我在第一次添加自动装配时自己完成了,但我也在配置中明确列出了订户。

您可以通过以下方式查看已注册的事件(并检查是否有多次注册以执行相同的服务/操作):

bin/console debug:event-dispatcher

答案 1 :(得分:0)

在我的symfony 4.2中,它是否取决于服务定义。

如果我这样定义服务,我的订户将被注册两次:

# oauth process listener
app.subscriber.oauth:
    class: App\EventListenerSubscriber\OauthSubscriber
    arguments: ['@session', '@router', '@security.token_storage', '@event_dispatcher', '@app.entity_manager.user', '@app.fos_user.mailer.twig_swift']
    tags:
        - { name: kernel.event_subscriber }

但是如果我将其定义为以下内容,它只会被注册一次:

# oauth process listener
App\EventListenerSubscriber\OauthSubscriber:
    arguments: ['@session', '@router', '@security.token_storage', '@event_dispatcher', '@app.entity_manager.user', '@app.fos_user.mailer.twig_swift']
    tags:
        - { name: kernel.event_subscriber }

我在github上发布了一个错误报告,并立即得到一个答案,即在较新的symfony版本中,事件监听器和订阅者会自动以其类名作为键进行注册(在某些默认情况下-必须对此主题进行阅读)。 因此,无需将它们明确注册为服务。 无论如何,我们都会这样做,但是使用任意键而不是类名,将有两个服务。