Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
TRACK

Symfony 3 >

Customize everything with Events

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We can override templates. We can override translations. We can override forms. But there's more than that. For example, after we finish registration, we're redirected to this registration confirmation page. You know what? I'd rather do something else: I'd rather redirect to the homepage and skip this page entirely. How can we do that?

Well, let's do a little bit of digging. If you hover over the route name in the web debug toolbar, you can see that this is page rendered by RegistrationController. Back in my editor I'll press Shift+Shift and look for RegistrationController in the bundle. Specifically, registerAction() is responsible for both rendering the registration page and processing the form submit.

And check this out: after the form is valid, it redirects to the confirmation page.

Events to the Rescue!

So at first, it seems like we need to override the controller itself. But not so fast! The controller - in fact every controller in FOSUserBundle is littered with events: REGISTRATION_INITIALIZE, REGISTRATION_SUCCESS, REGISTRATION_COMPLETED and REGISTRATION_FAILURE. Each of these represents a hook point where we can add custom logic.

In this case, if you look closely, you can see that after it dispatches an event called REGISTRATION_SUCCESS, below, it checks to see if the $event has a response set on it. If it does not, it redirects to the confirmation page. But if it does, it uses that response.

That's the key! If we can add a listener to REGISTRATION_SUCCESS, we can create our own RedirectResponse and set that on the event so that this controller uses it. Let's go!

Creating the Event Subscriber

Inside of AppBundle, create a new directory called EventListener. And in there, a new PHP class: how about RedirectAfterRegistrationSubscriber. Make this implement EventSubscriberInterface: the interface that all event subscribers must have. I'll use our favorite Code->Generate menu, or Command+N on a Mac, go to "Implement Methods" and select getSubscribedEvents.

... lines 1 - 2
namespace AppBundle\EventListener;
... lines 4 - 6
class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
}
}

We want to attach a listener to FOSUserEvents::REGISTRATION_SUCCESS, which, by the way, is just a constant that equals some string event name.

In getSubscribedEvents(), add FOSUserEvents::REGISTRATION_SUCCESS assigned to onRegistrationSuccess. This means that when the REGISTRATION_SUCCESS event is fired, the onRegistrationSuccess method should be called. Create that above: public function onRegistrationSuccess().

<?php
... lines 2 - 8
class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
public function onRegistrationSuccess(FormEvent $event)
{
}
public static function getSubscribedEvents()
{
return [
FOSUserEvents::REGISTRATION_SUCCESS => 'onRegistrationSuccess'
];
}
}

Oh, and notice that when this event is dispatched, the bundle passes a FormEvent object. That will be the first argument to our listener method: FormEvent $event. That's what we need to set the response onto.

Investigating all the Events

Before we go any further, I'll hold command and click into the FOSUserEvents class... cause it's awesome! It holds a list of every event dispatched by FOSUserBundle, what its purpose is, and what event object you will receive. This is gold.

Creating the RedirectResponse

Back in onRegistrationSuccess, we need to create a RedirectResponse and set it on the event. But to redirect to the homepage, we'll need the router. At the top of the class, create public function __construct() with a RouterInterface $router argument. Next, I'll hit Option+Enter, select "Initialize Fields" and choose router.

<?php
... lines 2 - 10
class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
private $router;
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
... lines 19 - 32
}

That was just a shortcut to create the private $router property and set it in the constructor: nothing fancy.

Now, in onRegistrationSuccess() we can say $url = $this->router->generate('homepage'), and $response = new RedirectResponse($url). You may or may not be familiar with RedirectResponse. In a controller, to redirect, you use $this->redirectToRoute(). In reality, that's just a shortcut for these two lines!

Finally, add $event->setResponse($response).

<?php
... lines 2 - 10
class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
... lines 13 - 19
public function onRegistrationSuccess(FormEvent $event)
{
$url = $this->router->generate('homepage');
$response = new RedirectResponse($url);
$event->setResponse($response);
}
... lines 26 - 32
}

Ok, this class is perfect! To tell Symfony about the event subscriber, head to app/config/services.yml. At the bottom, add app.redirect_after_registration_subscriber, set the class, and add autowire: true. By doing that, thanks to the RouterInterface type-hint, Symfony will automatically know to pass us the router.

Finally, add a tag on the bottom: name: kernel.event_subscriber. And we are done!

... lines 1 - 5
services:
... lines 7 - 22
app.redirect_after_registration_subscriber:
class: AppBundle\EventListener\RedirectAfterRegistrationSubscriber
autowire: true
tags:
- { name: kernel.event_subscriber }

Try it out! Go back to /register and signup as aquanaut5@gmail.com. Fill out the rest of the fields and submit!

Boom! Back to our homepage! You can customize just about anything with events. So don't override the controller. Instead, hook into an event!

Leave a comment!

42
Login or Register to join the conversation
Default user avatar

Works like a charm, the only thing I had to update is the type of $event parameter :

public function onRegistrationSuccess( **GetResponseUserEvent** $event)

17 Reply

Hey Sami

Were you having problems or why you had to change the type-hint of the $event argument?
I can see that FOSUserBundle still sends the "FormEvent" object: https://github.com/FriendsO...

Cheers!

Reply
Default user avatar
Default user avatar nacho lópez | posted 3 years ago | edited

Hi, This is a great tutorial, thanks for it.

My dude is: how can i go back to the App\Form\RegistrationType if i need? for example the email is already register.


public function onRegistrationSuccess(FormEvent $event)
  {
    $user = $this->userManager->createUser();
    $em = $this->em;
    $r = $em->getRepository('App:User');

    $form = $event->getForm();
    if ($form->isSubmitted()) {
      $email = $form->get('email');
      $email_data = $email->getData();
      $existe_email = $r->existeEmailUsername($email_data);
      if ($existe_email) {
          $event->getRequest()->getSession()->getFlashBag()->add('error', $this->translator->trans('Email already used.'));
          $event = new FormEvent($form, $event->getRequest());
          $dispatcher = new EventDispatcher();
          if (null === $response = $event->getResponse()) {
             $url = $this->router->generate('fos_user_registration_register');
             $response = new RedirectResponse($url);
             $event->setResponse($response);
         }
         // $dispatcher->dispatch($event, FOSUserEvents::REGISTRATION_FAILURE);
         // $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
         $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, new FilterUserResponseEvent($user, $event->getRequest(), $response));
         if (null !== $response = $event->getResponse()) {
            return $response;
         }
      }

Thanks a lot.

Reply

Hey Nacho,

> My dude is: how can i go back to the App\Form\RegistrationType if i need? for example the email is already register.

Just to clarify, I suppose you want to redirect user back to *login* page instead of register page if the give emails is already registered?

Actually, I'd recommend you to use a UniqueEntity (see https://symfony.com/doc/cur... ) for email field that will check if the give email is registered on form validation level, and if it is - the registration form will show a clear message about it.

Cheers!

Reply
Default user avatar
Default user avatar nacho lópez | Victor | posted 3 years ago

Hi Victor,

Thank you so much for answering so quickly.
Checking the email is just an example, what i am trying to do is to go back to the register form showing an error.

Best regards

Reply

Hey Nacho,

OK, perfect, then my suggestion about using UniqueEntity showing validation error should fit well for you I think.

Cheers!

Reply
Default user avatar
Default user avatar nacho lópez | Victor | posted 3 years ago

Hi victor,

Thanks again for answering.
I am sorry i did not express myself correctly.
The example that i would like to implement is:

I would like to use a promotional code. this promotional code do not belong to the user entity, so i can not use any Unique key o a validation on the form type. I need to check it on the onRegistrationSuccess and if the code is wrong [spelling o the code doesn't exist] go back to the from and show the error -> "this promotional code is not correct", but filling all fields of the form with the information already submitted.

Cheers! and thanks a lot for you time.

Reply

Hey Nacho,

See this code that is responsible for registration: https://github.com/FriendsO... - so when REGISTRATION_SUCCESS even is dispatched - form is already valid, that means use will be stored into DB before the redirect. Somehow, you need to make form invalid before that isValid() check if promo code is not valid or does not exist. For this, the only way I see is to override the registration form with your custom form. An this would be the first step, as you also want to render an additional field (called "promotional code" I suppose?) so it will be rendered in that form and users would be able to input the code there. Have you done that already?

Anyway, for more complex solutions, I'd recommend you to look into direction of Symfony Guard instead of using FOSUserBundle, Guard is much more flexible and you just write the any business logic you want from scratch. See this course for more information: https://symfonycasts.com/sc... . With FOSUserBundle you would need to override things to get it working

I hope this helps!

Cheers!

Reply
Default user avatar
Default user avatar nacho lópez | Victor | posted 3 years ago

Hi Victor,

Thanks a lot for your time. Of course your answer helps me. I have resolved it as you mention by doing my own controller, but when i saw this tutorial i was very impressive how register can be resolved in an easy way, so i was tempted to change everything.

It is true that FOSUserBundle force you to override a lot of things, but after many years using it i have a lot templates, services and controllers that i can reused easily. How knows in the future.
For those how doesn't know what are we talking about, create a register controller in src and use a different link to go there.
{# a href="{{ path('fos_user_registration_register') }}">{{ 'Regístrate'|trans }} /a #}
a href="{{ path('user_registration') }}">{{ 'Regístrate'|trans }} /a
At the controller use the registrationType in stead of defined it on the server.yml
$form = $this->createForm(RegistrationType::class, $user, $params);
And reused the templates of the fosuser bundles if you already have them
return $this->render('@FOSUser/Registration/register.html.twig', array(
'form' => $form->createView(),
'action' => $this->generateUrl('user_registration')
));
Do not forget to change the action to your new register controller, otherwise it will go to the fosuserbundles one.
You can override the templates at templates/bundles/FOSUserBundle/

Thanks a lot again for your help!

Cheers.

Reply

Hey Nacho,

Thanks for sharing your solution with others! And I'm happy you were able to got it working! :)

Cheers!

Reply
Default user avatar
Default user avatar Gavin Moulton | posted 3 years ago

Using exactly the same code in symfony 3.4 and it ignores the listener. Does version 3.4 have anything different, that needs a different setting or approach?

Reply

Hey Gavin Moulton

In 3.4 I think you need to configure your listeners and tag them

Docs about listeners: https://symfony.com/doc/3.4...

Cheers

Reply
Default user avatar
Default user avatar Guervyl | posted 4 years ago

Thank you so much for those videos. You just saved me some reading times. I hate reading!!! Because I read very slowly.

Well, I did not do exactly what you did in your video when you declare the service into app/.../services.yml and I was wondering why didn't you put it into myBundle/.../services.yml. So I declare the service into myBundle/.../services.yml. When I register I keep redirected to the fos_user_registration_confirmed route. Then I spent an hour trying to find out why it did not work (checking if I wrote badly some words, try Xdebug which did not debug event subscriber class and also set die() but nothing happend). I just remembered you said set it into app/.../services then I cut and paste the service code from myBundle/.../services.yml to app/.../services.yml then it works.

What is the difference between app/.../services.yml and myBundle/.../services.yml? Note that myBundle/.../services.yml is imported after app/.../services.yml in the app/.../config.yml.

Reply

Hey Guervyl

We're glad to hear that you are liking our videos :)

> What is the difference between app/.../services.yml and myBundle/.../services.yml?
As far as I know the only difference is the loading order. Symfony loads first your config from "app" folder

> why didn't you put it into myBundle/.../services.yml
That's because in Symfony4 you don't have a bundle structure anymore (ignoring third party bundles), all your code live inside "src" folder

I'm not sure why it started working after you moved the config from your bundle to the "app" folder but the good part is you now know that you don't have to split your config into many bundles

Cheers!

Reply
Jelle S. Avatar
Jelle S. Avatar Jelle S. | posted 5 years ago

Hi, first off, great tutorial as usual!
I want a newly registered user to redirect to a different route but I get this error:

The "MDBUserBundle" (from the _controller value "MDBUserBundle:User:confirmed") does not exist or is not enabled in your kernel! Did you mean "FOSUserBundle:User:confirmed"?

Reply

Hey Jelle,

Looks like your route does not registered in the application. You can double check it with consoler command:
bin/console debug:router --show-controllers | grep 'MDBUserBundle:User:confirmed'

Do you see your router in the output? Also, what do you exactly do to see this error, I mean, what code causes this error?

Cheers!

Reply
weaverryan Avatar weaverryan | SFCASTS | posted 5 years ago | edited

Yo there!

I would use an event subscriber for that :). Specifically, create a subscriber on the same event that we use in this chapter - FOSUserEvents::REGISTRATION_SUCCESS. The FormEvent object that you're passed allows you to say $user = $event->getForm()->getData(). You can then update the User object, and it will be saved by FOSUserBundle right after.

Try it out and let me know how it goes :).

Cheers!

Reply
Kaizoku Avatar
Kaizoku Avatar Kaizoku | posted 5 years ago

Wow ! Thank you this is cool !
I wish I knew this before I override all my controllers haha :D

Reply

Hey Kaizoku ,

Uh oh, sounds like a big piece of work ;) Yea, events rock! But sometimes you are not enough of them.

Cheers!

Reply
weaverryan Avatar weaverryan | SFCASTS | posted 5 years ago | edited

Hey Matt!

Woohoo! Nice work! And you're right, $form->handleRequest($request) does also populate data on the underlying object ($user) in this case. There are 2 ways to set the underlying data. Most commonly, we say (in a controller) $this->createForm(SomeFormType::class, $someObject). The second argument becomes the object that the form modifies. The other way is by calling $form->setData($someObject), as you saw here. But actually, they're the same :). The first is just a shortcut to create the form and then call setData() on it. Hopefully that clarifies even more!

Cheers!

Reply
Michael-K Avatar
Michael-K Avatar Michael-K | posted 5 years ago

Dear KnpUniversitiy-Team
First, thanks a lot for the really great tutorial!!
I added some other fields like name or firstname to the user entity. Now I Have the problem, that the validation of the form works for this new fields fine and when a field with @Assert\NotBlank() is missing, a nice note is displayed in the form. But when the email field is empty, no note is displayed, but the error "Column 'email' cannot be null" is displayed. How can I fix this? I tried to find a solution in the web, but I haven't' found a solutions which I understand.
Best regards!
Michael

Reply

Hey Michael K.

We are glad to hear you are liking our tutorials :)

Have you tried using translations ? you can customize any message from the system, if you don't know how, you can check the docs here http://symfony.com/doc/curr...
or even better, check our video about it: https://knpuniversity.com/s...

Have a nice day!

Reply
Michael-K Avatar

Hi Diego
Thanks a lot for the fast replay!
I don't think it's a translation problem. For me, it seems to be a validation problem. Because with my own fields it works perfect. But with the standard fields like email, only the error-screen of symfony is displayed.

Reply

I got you now! (Sorry, I misunderstood you)

Indeed you are missing your validations, and the reason is because FOSUserBundle add's them via "Validation Groups", you have to specify which group you want to use in your FormType's (actually there are more ways of doing it), in this case you want the "Registration" group, you can do it like this:


//Registration Form Type

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'validation_groups' => array('registration'),
    ));
}

You can read more about validation groups here http://symfony.com/doc/current/form/validation_groups.html
Or even better, we have a tutorial where Ryan explains it in a cool way https://knpuniversity.com/screencast/symfony-security/conditional-validation-groups

Cheers!

Reply
Michael-K Avatar

Dear Diego
And now I unterstand how it works and it works! ;-)
Thanks a lot for your help!
Michael

1 Reply
Kaizoku Avatar
Kaizoku Avatar Kaizoku | posted 5 years ago

Hello,

Unfortunatly it seems to be different for redirecting after LOGIN.
There is not login event.
I found this two events

return [
FOSUserEvents::SECURITY_IMPLICIT_LOGIN => 'onLogin',
SecurityEvents::INTERACTIVE_LOGIN => 'onLogin',
];

But then the $event in onLogin is not of the correct type and it's isn't working.
Is it possible to have the eventsubscriber working for login redirection ?

Reply

Hey Kaizoku

What you want to achieve?

By default, symfony redirects you back to the last requested page that caused you to login, or if there isn't one, you can setup a default route (via config.yml)
If this behaviour doesn't fit your needs, as always, you can customize it, but it will require more work. You can find a lot of info here: https://symfony.com/doc/cur...

I hope it helps you :)
Cheers!

Reply
Kaizoku Avatar

Hello Diego,

Thank you for your answer.
About login event it's a bit different than other events as I understood.
I had the redirection working implementing AuthenticationSuccessHandlerInterface instead of EventSubscriberInterface

class RedirectAfterLogin implements AuthenticationSuccessHandlerInterface {

private $router;

public function __construct(RouterInterface $router)
{
$this->router = $router;
}

public function onAuthenticationSuccess( Request $request, TokenInterface $token ) {
return new RedirectResponse($this->router->generate(...));
}
}

Reply

Ohhh the "AuthenticationSuccessHandlerInterface", interesting! I didn't know about it's existence. Thanks for sharing it!

Have a nice day :)

Reply
Default user avatar
Default user avatar Jürgen Schatral | posted 5 years ago

Hello together,
First, thankyou for your good work. I`ve tested your sample code - no problems. FOSUserEvents::REGISTRATION_SUCCESS is overriden and the "homepage" is displayed. But if I generate a new Symfony 3.3 application framework with friendsofsymfony/user-bundle the landing page with "The user has been created successfully.. " will be still dispayed but no homepage. If I debug onRegistrationSuccess in step over mode, I see how the line $this->router->generate('homepage') will be executed, but the result no homepage. Other FOSUserEvents do have the same problem. To avoid this problem I comment out all of the new code in services.yml but the result will be the same no homepage.
What is going wrong? Is there something more to do? Thank you... Greetings from Germany

Reply

Hey Jürgen Schatral

Can you show me the snippet of your listener ? I believe you forgot to attach the RedirectResponse object to the event, but I might be wrong

Cheers!

Reply
Default user avatar
Default user avatar Jürgen Schatral | MolloKhan | posted 5 years ago | edited

Dear Diego,
the code is identical to the code from your download - copy and paste. But I find a difference in the behavior if I disable the event in your sample code. A message shows that the new user is registered directly without sendig an e-mail to the user although the parameter.yml file has a correct mailer configuration.
Because of this behavior a take a look in my and your composer.json. I found differences in the version control
"friendsofsymfony/user-bundle" : "^2.0"
"friendsofsymfony/user-bundle" : "dev-master",
I don`t know how to handle that.

Here the copy of my code of the EventListener and my Composer.json for you. I hope it helps - Thank you. Greeting from Germany
Jürgen Schatral.


namespace AppBundle\EventListener;

use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
    use TargetPathTrait;

    private $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    public function onRegistrationSuccess(FormEvent $event)
    {
        // main is your firewall's name
        $url = $this->getTargetPath($event->getRequest()->getSession(), 'main');

        if (!$url) {
            $url = $this->router->generate('homepage');
        }

        $response = new RedirectResponse($url);
        $event->setResponse($response);
    }

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

Composer.json


{
    "name" : "js/istframework2",
    "license" : "proprietary",
    "type" : "project",
    "autoload" : {
        "psr-4" : {
            "AppBundle\\" : "src/AppBundle"
        },
        "classmap" : [
            "app/AppKernel.php",
            "app/AppCache.php"
        ]
    },
    "autoload-dev" : {
        "psr-4" : {
            "Tests\\" : "tests/"
        },
        "files" : [
            "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
        ]
    },
    "require" : {
        "php" : ">=5.5.9",
        "doctrine/doctrine-bundle" : "^1.6",
        "doctrine/orm" : "^2.5",
        "friendsofsymfony/user-bundle" : "dev-master",
        "incenteev/composer-parameter-handler" : "^2.0",
        "sensio/distribution-bundle" : "^5.0.19",
        "sensio/framework-extra-bundle" : "^3.0.2",
        "symfony/monolog-bundle" : "^3.1.0",
        "symfony/polyfill-apcu" : "^1.0",
        "symfony/swiftmailer-bundle" : "^2.3.10",
        "symfony/symfony" : "3.3.*",
        "twig/twig" : "^1.0||^2.0"
    },
    "require-dev" : {
        "sensio/generator-bundle" : "^3.0",
        "symfony/phpunit-bridge" : "^3.0"
    },
    "scripts" : {
        "symfony-scripts" : [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
        ],
        "post-install-cmd" : "@symfony-scripts",
        "post-update-cmd" : "@symfony-scripts"
    },
    "config" : {
        "sort-packages" : true
    },
    "extra" : {
        "symfony-app-dir" : "app",
        "symfony-bin-dir" : "bin",
        "symfony-var-dir" : "var",
        "symfony-web-dir" : "web",
        "symfony-tests-dir" : "tests",
        "symfony-assets-install" : "relative",
        "incenteev-parameters" : {
            "file" : "app/config/parameters.yml"
        }
    }
}
Reply
Default user avatar
Default user avatar Jürgen Schatral | Jürgen Schatral | posted 5 years ago | edited

Sorry I have made a mistake here is the EventListerner again...
Mfg. J.Schatral


class RedirectAfterRegistrationSubscriber implements EventSubscriberInterface
{
    use TargetPathTrait;

    private $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    public function onRegistrationSuccess(FormEvent $event)
    {
        // main is your firewall's name
        $url = $this->getTargetPath($event->getRequest()->getSession(), 'main');

        if (!$url) {
            $url = $this->router->generate('homepage');
        }

        $response = new RedirectResponse($url);
        $event->setResponse($response);
    }

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

Oh, you installed the "Dev" branch of FOSUserBundle, just change it to: "friendsofsymfony/user-bundle" : "^2.0"
as we do (composer.json), and run: composer update friendsofsymfony/user-bundle

If it doesn't fix it, I believe your listener is not been fired, what it means is, the listener is not registered, try adding a `die()` statement so we can tell if it's been executed or not, so we can keep debugging :)

Cheers!

Reply
Default user avatar
Default user avatar Jürgen Schatral | MolloKhan | posted 5 years ago

Okay, if changed the version and run an composer update, clean and warm up the project...
If have set a breakpoint in the event onRegistrationSuccess() it halted definitly at the line with $url = $this->router->generate('homepage');
$response = new RedirectResponse($url); Debug information shows me that:
HTTP/1.0 302 Found
Cache-Control: no-cache, private
Date: Thu, 10 Aug 2017 10:33:32 GMT
Location: /ISTFramework2/web/app_dev.php/

<html>
<head>
<meta charset="UTF-8"/>
<meta http-equiv="refresh" content="1;url=/ISTFramework2/web/app_dev.php/"/> <title>Redirecting to /ISTFramework2/web/app_dev.php/</title>
</head>
<body>
Redirecting to /ISTFramework2/web/app_dev.php/.
</body>
</html>
The next line
$event->setResponse($response); brings me back zu my old problem :-)
Why not "Dev" instead of "^2.0" - Thank you!
Greeting from Germany

Reply

> Why not "Dev" ?
Because Dev branches might contain unknown bugs or backward incompatibilities

Hmm, look's like it is trying to redirect you to the homepage, exactly what you want, isn't it ?

Reply
Default user avatar
Default user avatar Jürgen Schatral | MolloKhan | posted 5 years ago

Yes! At that point It look`s like, but it doesn`t :-)

Reply

Hmm, interesting, what does it do after ? could you open your browser's debugger and check the response status ?

Also I just noticed this line: $url = $this->getTargetPath($event->getRequest()->getSession(), 'main');
You are passing the whole session, I believe you need to access to the property which contains the name or the URL

Reply
Default user avatar
Default user avatar Jürgen Schatral | MolloKhan | posted 5 years ago | edited

First the Response status:


HTTP status 200 OK
Controller RegistrationController :: registerAction
Controller class FOS\UserBundle\Controller\RegistrationController
Route name fos_user_registration_register
Has session yes

Second the url property:


$url = $this->getTargetPath($event->getRequest()->getSession(), 'main');
 if (!$url) {
       $url = $this->router->generate('homepage');
    #Debugger shows /ISTFramework2/web/app_dev.php/  
 }

Yes you are right the whole session will be used to reference to the $url at first but the $url will be empty and the access to the property which contain the name followed in the if block in the next code line.
After the execution of the overriden method we landed in C:/xampp/htdocs/ISTFramework2/vendor/friendsofsymfony/user-bundle/EventListener/EmailConfirmationListener.php.FOS\UserBundle\EventListener\EmailConfirmationListener->onRegistrationSuccess().
After that a e-mail confirmation will be send and the FOSUserEvents::REGISTRATION_COMPLETED event will dispatched and the homepage event will be ignored again.

...But this code is identical to your download version and nothing has changed.
If it is posible for you to generate a simple new Symfony 3.3 application with friendsofsymfony/user-bundle with a copy of the eventlisner from your download code you can simply debug it with phpstorm or eclipse.
It is not much work. I think if you debug it on your own you see something more what I don`t see... :-) After that you can upload a actual version Symfony 3.3 application without errors - if possible
Thank you! Greetings from Germany.

Reply

Yo Jürgen Schatral!

Well, this is very interesting! So first, I don't think the issue is Symfony 3.3 - I can't think of a reason why this would cause an issue, and you (very smartly) tried commenting out all the new Symfony 3.3 services.yml code, which didn't change anything. Also, I just tried it :). I downloaded a fresh Symfony 3.3 project, installed FOSUserBundle, copy and pasted your subscriber and... it works! I'm redirected to the homepage as expected. You can see the code here: https://github.com/weaverryan/tmp-sf33-fosu

The issue is something different - and you discovered it in your last message: if you activate the email confirmation step, then that overrides the response that you're setting. The fix is a bit odd: you need to set the priority of your subscriber to be lower than the EmailConfirmationListener, so that your listener is called after. The change should look like this in your subscriber


    public static function getSubscribedEvents()
    {
        return [
            // use a -5 priority - the other listener uses a 0 priority
            FOSUserEvents::REGISTRATION_SUCCESS => ['onRegistrationSuccess', -5]
        ];
    }

I haven't tested this, so let me know if it works. And great issue - very tricky!

Cheers!

1 Reply
Default user avatar
Default user avatar Jürgen Schatral | weaverryan | posted 5 years ago

Thank you that`s it! It works with redirection to the homepage.

After that we looked again in you documention file controller_envents.rst - "Registration success listener with enabled confirmation at the same time". We have read your documention before but we have read it so badly. The solution of this facts stood very near by us, but we don`t have seen it. ...To change the priority is not so unusual. Now we are shure that we have with this bundle a great range of flexibity. We have learned a lot. Thank you for that.
Greeting from Germany - J.Schatral

Reply

Ah, I'm so happy it worked! Thanks for following up and good luck! :)

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.3.*", // v3.3.18
        "doctrine/orm": "^2.5", // v2.7.0
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.5.4
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.3.0
        "sensio/distribution-bundle": "^5.0", // v5.0.18
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.25
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "knplabs/knp-markdown-bundle": "^1.4", // 1.5.1
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "friendsofsymfony/user-bundle": "^2.0" // v2.0.0
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.4
        "symfony/phpunit-bridge": "^3.0", // v3.2.7
        "nelmio/alice": "^2.1", // v2.3.1
        "doctrine/doctrine-fixtures-bundle": "^2.3", // v2.4.1
        "symfony/web-server-bundle": "^3.3"
    }
}
userVoice