【免费下载链接】zend-eventmanager
Implement event systems, signal slots, intercepting filters, and observers.
还在逐个事件手动 attach 监听器吗?PHP 事件管理组件zend-eventmanager的通配符监听器(Wildcard Listeners)允许你用一个星号*让单个监听器捕获所有事件——后续新增事件也无需改动代码。本文用简单示例带你掌握EventManager与SharedEventManager下的通配符用法、执行顺序与移除方法,一看就会。
🎯 为什么需要通配符监听器?
在典型的"信号槽"(signal slots)场景里,一个对象会触发多种命名事件,比如save、delete、update。如果你的逻辑需要对每个事件都做出反应(例如统一记录日志、统一计时),逐名注册会写出大量重复代码:
$events->attach('save', $logger); $events->attach('delete', $logger); $events->attach('update', $logger); // ...事件再多一个,就要再多写一行而通配符监听器只需一行,任何事件触发时它都会收到通知,这正是 doc/book/wildcard-listeners.md 中所描述的"attach to all events"能力。
✅ 三步上手:给 EventManager 挂上通配符监听器
只需在attach()的第一个参数传*,即可监听当前EventManager实例上的所有事件:
use Zend\EventManager\EventManager; $events = new EventManager(); $events->attach('*', function ($e) { // 任何事件触发时,这里都会收到通知 var_dump($e->getName()); }); $events->trigger('save'); // 输出 "save" $events->trigger('delete'); // 输出 "delete"实现原理并不神秘:触发事件时,EventManager会把注册在*下的监听器合并进当前事件的监听队列中,相关逻辑见 src/EventManager.php。
💡 提示:通配符监听器同样支持第三个参数
$priority,且该优先级对所有被触发的事件生效。
🎯 SharedEventManager 通配符的三种组合
SharedEventManager的attach()接收两个字符串参数:标识符(identifier,代表"哪个上下文/组件")和事件名。两个参数都可以使用通配符,组合出四种覆盖范围:
| 写法 | 含义 |
|---|---|
attach('foo', '*', $listener) | 监听 "foo" 上下文下的所有事件 |
attach('*', 'foo', $listener) | 监听任意上下文的 "foo" 事件 |
attach('*', '*', $listener) | 监听所有上下文的所有事件 |
$sharedEvents = new SharedEventManager(); // "foo" 上下文的所有事件 $sharedEvents->attach('foo', '*', $listener); // 任意上下文的 "foo" 事件 $sharedEvents->attach('*', 'foo', $listener); // 所有上下文的所有事件 $sharedEvents->attach('*', '*', $listener);触发事件时,SharedEventManager::getListeners()会把命中各层通配符的监听器与精确匹配的一起返回,合并逻辑可参考 src/SharedEventManager.php。
⏱️ 执行顺序:优先级才是关键
两个容易忽略的行为细节:
- 优先级统一生效:attach 时指定的
$priority会应用于该通配符监听器匹配的每一个事件。 - 同优先级下,精确监听器先执行,通配符监听器后执行。这样能保证"专项处理"先于"通用处理",例如:
$events->attach('*', function ($e) { echo "wildcard\n"; }, 5); $events->attach('test', function ($e) { echo "explicit\n"; }, 5); $events->trigger('test'); // 输出:explicit 在前,wildcard 在后该行为有专门的测试用例保障,见 test/EventManagerPriorityTest.php。
🧹 如何优雅地移除通配符监听器?
detach()第二个参数传*(或直接省略),即可把监听器从所有事件上摘除:
$events->detach($listener, '*'); // 等价于 $events->detach($listener)内部会遍历所有已注册的事件逐一移除,实现位于 src/EventManager.php。
📚 小结与延伸阅读
| 要点 | 结论 |
|---|---|
EventManager通配符 | attach('*', $listener),覆盖该实例全部事件 |
SharedEventManager通配符 | 标识符、事件名可独立或同时用* |
| 优先级 | 对全部命中事件统一生效 |
| 同优先级顺序 | 精确监听器先于通配符监听器 |
| 移除 | detach($listener, '*')一次清空 |
想进一步上手,建议按顺序阅读官方文档:doc/book/quick-start.md → doc/book/tutorial.md(Wildcards 章节)→ doc/book/api.md。掌握通配符监听器后,你的 PHP 事件代码将告别重复,真正做到"一处注册,处处响应"。🚀
【免费下载链接】zend-eventmanager
Implement event systems, signal slots, intercepting filters, and observers.
相关推荐
终极指南:如何使用Mitt通配符事件监听捕获所有事件
终极指南:如何使用Mitt通配符事件监听捕获所有事件 Mitt是一个轻量级的事件发射器库,体积不到200字节,却提供了强大的事件处理功能。本文将详细介绍如何利用
开发工具5分钟搞定多系统启动盘:Ventoy让你的U盘变身系统百宝箱
5分钟搞定多系统启动盘:Ventoy让你的U盘变身系统百宝箱 你是不是还在为每个操作系统准备一个U盘而烦恼?或者每次重装系统都要重新格式化启动盘?今天我要介绍的
操作系统固件开发工具在 React 中通过 SWR Subscription 去重全局事件监听器:从 N 个监听器到 1 个监听器
在 React 中通过 SWR Subscription 去重全局事件监听器:从 N 个监听器到 1 个监听器 导读 在 React 应用中,多个组件实例同时订
金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考