gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
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.
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!
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()
.
... 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.
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.
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
.
... 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)
.
... 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!
// 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"
}
}