问题描述
我想在 cakePHP2.10 中从我的控制器分派一个事件。因此我需要为控制器注册事件监听器。当事件从我的模型发出时,实现这一点很简单,但我无法为我的控制器弄清楚。从书中: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());
控制器会是这样吗,还是我只能对控制器发出的事件使用全局事件?
App::uses('TestController','Controller');
$test = new TestController();
$test->getEventManager()->attach(new TestEventsListener());
我也为 cakePHP3 看到了这个:CakePHP 3 Controller Event Implementation Example 但我不确定如何为 cakePHP2.x 调整它。谢谢
解决方法
您永远不应该手动实例化控制器(可能在单元测试中除外),如果您觉得有必要这样做,那么这表明您的应用程序架构中可能存在缺陷。
与模型不同,每个请求只能涉及一个控制器(如果有多个,这将再次表明存在架构缺陷),因此理想情况下,您没有理由将侦听器附加到特定的控制器实例.
我想说的是,如果您有多个控制器来调度该事件,但您只想听其中一个,那么这又是一个可能的架构缺陷,很可能可以通过以下方式解决在该特定控制器中正确确定事件范围,例如使用像 Controller.Test.myEvent
这样的特定控制器名称。在您的听众中,您还可以检查主题是否是特定实例,但如果听众需要了解有关主题的那么多,那么这可能不太好。
说了这么多,是的,请改用全局事件管理器,它与链接答案中的原理相同,例如:
// 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...
}
}
然后在您的控制器中相应地分派您的事件:
$event = new CakeEvent('Controller.Test.myEvent',$this,array(
'some' => $eventData
));
$this->getEventManager()->dispatch($event);
另见
- Cookbook > Core Libraries > General Purpose > Events System > Registering Listeners
- Cookbook > Core Libraries > General Purpose > Events System > Registering Global Listeners
这是我的错误。我试图实例化控制器以附加侦听器,但我应该这样做:
CakeEventManager::instance()->attach(new TestListener());