I want to create custom events called user_logged so that i can attach my listeners to those events.
I want to execute few functions whenever user has logged in.
Create a class which extends Symfony\Component\EventDispatcher\Event.
Then, use the event dispatcher service to dispatch the event:
$eventDispatcher = $container->get('event_dispatcher');
$eventDispatcher->dispatch('custom.event.identifier', $event);
You can register your event listener service like so:
tags:
- { name: kernel.event_listener, event: custom.event.identifier, method: onCustomEvent }
This answer is little bit extend answer.
services.yml
custom.event.home_page_event:
class: AppBundle\EventSubscriber\HomePageEventSubscriber
tags:
- { name: kernel.event_listener, event: custom.event.home_page_event, method: onCustomEvent }
AppBundle/EventSubscriber/HomePageEventSubscriber.php
namespace AppBundle\EventSubscriber;
class HomePageEventSubscriber
{
public function onCustomEvent($event)
{
var_dump($event->getCode());
}
}
AppBundle/Event/HomePageEvent.php
namespace AppBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class HomePageEvent extends Event
{
private $code;
public function setCode($code)
{
$this->code = $code;
}
public function getCode()
{
return $this->code;
}
}
anywhere you wish, for example in home page controller
use AppBundle\Event\HomePageEvent;
// ...
$eventDispatcher = $this->get('event_dispatcher');
$event = new HomePageEvent();
$event->setCode(200);
$eventDispatcher->dispatch('custom.event.home_page_event', $event);
Related
This is the first time ever I am working with creating custom event dispatcher and subscriber so I am trying to wrap my head around it and I cant seem to find out why my custom event is not being dispatched.
I am following the documentation and in my case I need to dispatch an event as soon as someone registers on the site.
so inside my registerAction() I am trying to dispatch an event like this
$dispatcher = new EventDispatcher();
$event = new RegistrationEvent($user);
$dispatcher->dispatch(RegistrationEvent::NAME, $event);
This is my RegistrationEvent class
namespace AppBundle\Event;
use AppBundle\Entity\User;
use Symfony\Component\EventDispatcher\Event;
class RegistrationEvent extends Event
{
const NAME = 'registration.complete';
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function getUser(){
return $this->user;
}
}
This is my RegistrationSubscriber class
namespace AppBundle\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class RegistrationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
KernelEvents::RESPONSE => array(
array('onKernelResponsePre', 10),
array('onKernelResponsePost', -10),
),
RegistrationEvent::NAME => 'onRegistration'
);
}
public function onKernelResponsePre(FilterResponseEvent $event)
{
// ...
}
public function onKernelResponsePost(FilterResponseEvent $event)
{
// ...
}
public function onRegistration(RegistrationEvent $event){
var_dump($event);
die;
}
}
After doing this, I was hoping that the registration process would stop at the function onRegistration but that did not happen, I then looked at the Events tab of the profiler and I do not see my Event listed their either.
What am I missing here? A push in right direction will really be appreciated.
Update:
I thought i need to register a service for the custom event so I added the following code inside services.yml
app.successfull_registration_subscriber:
class: AppBundle\Event\RegistrationSubscriber
arguments: ["#doctrine.orm.entity_manager"]
tags:
- { name: kernel.event_subscriber}
Inside the Event tab of profiler I do see my custom event being listed but it still does not dispatch.
By creating your own EventDispatcher instance you dispatch an event that can never be listened to by other listeners (they are not attached to this dispatcher instance). You need to use the event_dispatcher service to notify all listeners you have tagged with the kernel.event_listener and kernel.event_subscriber tags:
// ...
class RegistrationController extends Controller
{
public function registerAction()
{
// ...
$this->get('event_dispatcher')->dispatch(RegistrationEvent::NAME, new RegistrationEvent($user););
}
}
Duplicate of dispatcher doesn't dispatch my event symfony
With auto-wiring, it is now better to inject the EventDispatcherInterface
<?php
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
//...
class DefaultController extends Controller
{
public function display(Request $request, EventDispatcherInterface $dispatcher)
{
//Define your event
$event = new YourEvent($request);
$dispatcher->dispatch(YourEvent::EVENT_TO_DISPATCH, $event);
}
}
I'm trying to use https://github.com/fervo/FervoDeferredEventBundle in order to have async events to store data in my DB. The event is added to the RabbitMQ Queue correctly but the event listener and the event itself is never executed.
I'm trying in both ways: first letting the listener to do the job and also dispatching manually the deferevent.
Any idea?
Thank you!
My code:
in my Controller:
$event = new DeferEvent('save.data', new SaveDataEvent($data));
$this->get('event_dispatcher')->dispatch('fervo.defer', $event);
SaveDataEvent.php
<?php
namespace AppBundle\Event;
use Symfony\Component\EventDispatcher\Event;
class SaveDataEvent extends Event
{
protected $data;
public function __construct($data)
{
$this->data = $data;
}
public function getData()
{
return $this->data;
}
public function saveData()
{
$data = $this->getData();
// do more stuff
}
}
SaveDataListener.php
<?php
namespace AppBundle\EventListener;
use AppBundle\Event\SaveDataEvent;
class SaveDataListener
{
/**
* #var SaveDataEvent
*/
public function onSendData(SaveDataEvent $event)
{
$data = $event->saveData();
}
}
services.yml
app.save_data_listener:
class: AppBundle\EventListener\SaveDataListener
tags:
-
name: kernel.event_listener #fervo_deferred_event.listener
event: send.data
Reading the docs, you should fix the services.yml:
app.save_data_listener:
class: AppBundle\EventListener\SaveDataListener
tags:
name: fervo_deferred_event.listener
event: fervo.defer
Replace fervo.defer with the first value passed to dispatch() method if you want, it's the name of the dispatched event.
I want to do some post-processing after sending a response object in my Symfony controller. Problem is, the post-processing requires other methods contained in my controller object. I'd like to do something like this:
public function testAction() {
$dispatcher = new EventDispatcher();
$dispatcher->addListener('kernel.terminate', function (Event $event) {
$controller->get('logger');
$logger->info('hello');
});
return new Response();
}
How can I inject the $controller variable into my kernel.terminate post-processing?
it seems you need only the container in your service. To get the container injected into your event listener I prefer to create a separate EventListener which you have to register in your container see code:
First create event listener class:
<?php
namespace Acme\DemoBundle\Listener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
class RequestListener
{
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
$logger = $this->container->get('logger')->getToken();
$logger->info('.....');
}
}
As you can see, we have now the service container injected and we are able to use it.
Next you have to register the service and inject the service container:
services:
acme.demo.listener.request:
class: Acme\DemoBundle\Listener\RequestListener
arguments: [ #service_container ]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
Notice in your case you have to select the event you wanna inject to. In my case I used the kernel.request event. You have to select the kernel.terminate event.
That can also be helpful: http://symfony.com/doc/current/cookbook/service_container/event_listener.html
I have a program with two bundles. One of them (CommonBundle) dispatches an event "common.add_channel", while a service on the other one (FetcherBundle) was supposed to be listening to it. On the profiler, I can see the event common.add_channel in the "Not Called Listeners" section. I don't get why symfony is not registering my listener.
This is my action, inside CommonBundle\Controller\ChannelController::createAction:
$dispatcher = new EventDispatcher();
$event = new AddChannelEvent($entity);
$dispatcher->dispatch("common.add_channel", $event);
This is my AddChannelEvent:
<?php
namespace Naroga\Reader\CommonBundle\Event;
use Symfony\Component\EventDispatcher\Event;
use Naroga\Reader\CommonBundle\Entity\Channel;
class AddChannelEvent extends Event {
protected $_channel;
public function __construct(Channel $channel) {
$this->_channel = $channel;
}
public function getChannel() {
return $this->_channel;
}
}
This was supposed to be my listener (FetcherService.php):
<?php
namespace Naroga\Reader\FetcherBundle\Service;
class FetcherService {
public function onAddChannel(AddChannelEvent $event) {
die("It's here!");
}
}
And here's where I register my listener (services.yml):
kernel.listener.add_channel:
class: Naroga\Reader\FetcherBundle\Service\FetcherService
tags:
- { name: kernel.event_listener, event: common.add_channel, method: onAddChannel }
What am I doing wrong? Why isn't symfony calling the event listener when I dispatch common.add_channel?
The new event dispatcher doesn't know anything about the listeners set on another dispatcher.
In your controller, you need to access the event_dispatcher service. A Compiler Pass of the Framework Bundle attached all listeners to this dispatcher. To get the service, use the Controller#get() shortcut:
// ...
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ChannelController extends Controller
{
public function createAction()
{
$dispatcher = $this->get('event_dispatcher');
// ...
}
}
I'm trying to do a redirect when a user impersonates another user.
For this I registered a service:
ACME_listener.security_switch_user:
class: ACME\CustomerLoginBundle\Listener\SecuritySwitchUserListener
arguments: [#service_container, #router, #security.context]
tags:
- { name: kernel.event_listener, event: security.switch_user, method: onSecuritySwitchUser }
My listener class looks like this:
namespace ACME\CustomerLoginBundle\Listener;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
class SecuritySwitchUserListener implements ListenerInterface {
public function __construct($appContainer, $router) {
$this->router = $router;
$this->appContainer = $appContainer;
}
public function onSecuritySwitchUser(SwitchUserEvent $event) {
echo "im in here!";
// this does get called
}
public function handle(GetResponseEvent $event) {
echo "but not here :(";
// this does not get called!
}
}
Now the problem is that I can not redirect the user from within the onSecuritySwitchUser method. Returning a RedirectResponse does NOT work and the SwitchUserEvent does NOT have a setResponse() method.
What do I have to do so that the handle() method does get called?
I think that handle() is called from onSecuritySwitchUser(). But I can be wrong.
UPDATE
You can overwrite the event with your own request :)
Look at:
Symfony\Component\Security\Http\Firewall\SwitchUserListener
And then Dispach new SwitchUserEvent with overwritten request
if (null !== $this->dispatcher) {
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
}
Maybe that will help you.