简体   繁体   中英

How to register event listeners for a controller in Cakephp2?

I want to dispatch an event from my controller in cakephp2.10. Therefore I need to register the event listener for the controller. It is simple to achieve this when the event is emitted from my model, but I cannot figure it out for my controller. From the book: https://book.cakephp.org/2/en/core-libraries/events.html#global-event-manager :

App::uses('ClassRegistry', 'Utility');
App::uses('UserEventsListener', 'Lib/Event');
$User = ClassRegistry::init('User');
$User->getEventManager()->attach(new UserEventsListener());

Would it be something like this for controllers, or am I only able to use global events for events emitted from controllers?

App::uses('TestController', 'Controller');
$test = new TestController();
$test->getEventManager()->attach(new TestEventsListener());

I also saw this for cakephp3: CakePHP 3 Controller Event Implementation Example but am not sure how to adapt this for cakephp2.x. Thanks

You should never manually instantiate a controller (except for maybe in unit tests), if you feel the need to do that, then this indicates a possible flaw in your application's architecture.

Unlike models, there can be only one controller involved per request (if there were more than one, this would again indicate an architectural flaw), so ideally there should be no reason for you to attach your listener to a specific controller instance.

I would go out on a limb and say that also if you have multiple controllers that dispatch that event, but you only want to listen to one of them, then that's again a possible architectural flaw, which could most likely be resolved by scoping the event properly in that specific controller, for example using a specific controller name like Controller.Test.myEvent . In your listener you could also check the subject whether it's a specific instance, but if the listener needs to know that much about the subject, then that's probably not good.

All that being said, yes, use the global event manager instead, it's the same principal as in the linked answer, for example:

// In app/Lib/Event/TestEventsListener.php
App::uses('CakeEventListener', 'Event');

class TestEventsListener implements CakeEventListener {

    public function implementedEvents() {
        return array(
            'Controller.Test.myEvent' => 'testScopedMyEvent',
        );
    }

    public function myEvent($event) {
        // testScopedMyEvent happend, do something...
    }
}

and then dispatch your event accordingly in your controller:

$event = new CakeEvent('Controller.Test.myEvent', $this, array(
    'some' => $eventData
));
$this->getEventManager()->dispatch($event);

See also

Here was my mistake. I was trying to instantiate the controller in order to attach the listener, but I should have just done this:

CakeEventManager::instance()->attach(new TestListener());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM