简体   繁体   English

如何在 Cakephp2 中为 controller 注册事件监听器?

[英]How to register event listeners for a controller in Cakephp2?

I want to dispatch an event from my controller in cakephp2.10.我想在 cakephp2.10 中从我的 controller 调度一个事件。 Therefore I need to register the event listener for the controller.因此我需要为 controller 注册事件监听器。 It is simple to achieve this when the event is emitted from my model, but I cannot figure it out for my controller.当事件从我的 model 发出时,很容易实现这一点,但我无法为我的 controller 弄清楚。 From the book: https://book.cakephp.org/2/en/core-libraries/events.html#global-event-manager :从书中: 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.我还为 cakephp3 看到了这个: CakePHP 3 Controller 事件实现示例,但我不确定如何将它用于 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.你永远不应该手动实例化 controller(可能在单元测试中除外),如果你觉得有必要这样做,那么这表明你的应用程序架构中可能存在缺陷。

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.与模型不同,每个请求只能涉及一个 controller(如果有多个,这将再次表明存在架构缺陷),因此理想情况下,您应该没有理由将侦听器附加到特定的 controller 实例。

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 .我会说 go 并说如果您有多个调度该事件的控制器,但您只想听其中一个,那么这又是一个可能的架构缺陷,很可能通过确定事件范围来解决正确地在特定的 controller 中,例如使用特定的 controller 名称,如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:然后在您的 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:我试图实例化 controller 以附加侦听器,但我应该这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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