Search code examples
symfonyfosuserbundle

Cannot autowire service in Symfony 3.4 and FosUserBundle


I try to override REGISTRATION_SUCCESS in FosUserBundle to redirect the admin on user's list after register a new user.

So I have created a new event subscriber :

<?php
namespace AppBundle\EventListener;

use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Mailer\MailerInterface;
use FOS\UserBundle\Util\TokenGeneratorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
    private $mailer;
    private $tokenGenerator;
    private $router;

    public function __construct(MailerInterface $mailer, TokenGeneratorInterface $tokenGenerator, UrlGeneratorInterface $router)
    {
        $this->mailer = $mailer;
        $this->tokenGenerator = $tokenGenerator;
        $this->router = $router;
    }

    public function onRegistrationSuccess(FormEvent $event)
    {
        $user = $event->getForm()->getData();

        $user->setEnabled(false);
        if (null === $user->getConfirmationToken()) {
            $user->setConfirmationToken($this->tokenGenerator->generateToken());
        }

        $this->mailer->sendConfirmationEmailMessage($user);

        $url = $this->router->generate('user_index');
        $event->setResponse(new RedirectResponse($url));
    }

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

and the following service :

app.redirect_after_registration_subscriber:
    class: AppBundle\EventListener\RedirectAfterRegistrationSubscriber
    arguments: ['@fos_user.mailer', '@fos_user.util.token_generator', '@router']
    tags:
        - { name: kernel.event_subscriber }

I don't understand why this error appears :

Cannot autowire service "AppBundle\EventListener\RedirectAfterRegistrationSubscriber": 
argument "$mailer" of method "__construct()" references interface 
"FOS\UserBundle\Mailer\MailerInterface" but no such service exists. You should maybe alias
this interface to one of these existing services: "fos_user.mailer.default",
"fos_user.mailer.twig_swift", "fos_user.mailer.noop".

Solution

  • I suppose you are using autodiscovering of services. Something like:

    # services.yaml
    
    AppBundle\:
        resource: '../src/'
    ...
    

    So in addition to the @app.redirect_after_registration_subscriber that you define, Symfony defines another service with id @AppBundle\EventListener\RedirectAfterRegistrationSubscriber. Both point to AppBundle\EventListener\RedirectAfterRegistrationSubscriber class. Yet you configured the mailer parameter only for the first one.

    The solution:

    AppBundle\EventListener\RedirectAfterRegistrationSubscriber:
        arguments: ['@fos_user.mailer', '@fos_user.util.token_generator', '@router']
        tags:
            - { name: kernel.event_subscriber }
    

    With autowiring and autoconfigure you can even sypmlify to:

    AppBundle\EventListener\RedirectAfterRegistrationSubscriber:
        arguments:
            $mailer: '@fos_user.mailer'