CakePHP中如何监听插件表的afterSave事件?
解决插件模型afterSave事件不触发的问题
首先,你不需要急着升级CakePHP,这个问题大概率是事件绑定的方式不对,而非版本bug导致的。
你现在在主应用Bootstrap里绑定插件模型的事件却没生效,核心原因是:在Bootstrap阶段获取的Contacts.contacts表实例,未必是后续保存操作时实际使用的那个实例——CakePHP处理请求时,可能会重新实例化表对象,导致你之前绑定的事件直接丢失了。
给你两个靠谱的解决办法:
方法1:在插件的Table类里绑定事件(推荐)
这是最贴合CakePHP插件封装理念的做法,把事件绑定放在插件自己的ContactsTable类中,确保每次实例化这个表时事件都会被正确绑定。
打开插件目录下的src/Model/Table/ContactsTable.php,在initialize方法中添加事件绑定代码:
public function initialize(array $config) { parent::initialize($config); $this->eventManager()->on('Model.afterSave', ['priority' => 1], function($event, $entity) { pr("afterSave - "); \Cake\Log\Log::write('info','afterSave'); }); }
这样不管是主应用调用插件模型,还是插件内部使用,只要保存Contacts数据,afterSave事件都会正常触发。
方法2:使用全局事件管理器监听
如果你一定要在主应用里绑定事件,可以通过全局事件管理器监听所有Model.afterSave事件,再过滤出你需要的插件模型:
修改你在主应用Bootstrap里的代码:
Log::write('info','foo'); \Cake\Event\EventManager::instance()->on('Model.afterSave', ['priority' => 1], function($event, $entity) { $table = $event->subject(); // 检查当前触发事件的表是否为插件的ContactsTable if ($table instanceof \Contacts\Model\Table\ContactsTable) { pr("afterSave - "); \Cake\Log\Log::write('info','afterSave'); } });
这种方式可以捕获所有模型的afterSave事件,再精准匹配你需要的插件模型执行逻辑。
最后补充一句:虽然升级到CakePHP 3系列的最新稳定版(比如3.10.x)能获得更多安全更新和功能优化,但你的当前问题不需要通过升级解决,调整事件绑定方式就能搞定。
内容的提问来源于stack exchange,提问作者trafalgar
相关产品推荐
相关产品推荐

