{"id":17249463,"url":"https://github.com/inhere/php-event-manager","last_synced_at":"2025-10-30T03:46:01.284Z","repository":{"id":56991489,"uuid":"107138880","full_name":"inhere/php-event-manager","owner":"inhere","description":"PHP event manager. simple, fully functional event management dispatcher implementation. 简洁,功能完善的事件管理实现，支持快速的事件组注册，设置事件优先级，通配符事件的监听。","archived":false,"fork":false,"pushed_at":"2019-01-19T15:13:15.000Z","size":91,"stargazers_count":27,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T19:52:06.863Z","etag":null,"topics":["event","event-management","psr-14"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inhere.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-16T14:28:10.000Z","updated_at":"2024-11-01T11:47:32.000Z","dependencies_parsed_at":"2022-08-21T10:10:41.408Z","dependency_job_id":null,"html_url":"https://github.com/inhere/php-event-manager","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhere%2Fphp-event-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhere%2Fphp-event-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhere%2Fphp-event-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inhere%2Fphp-event-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inhere","download_url":"https://codeload.github.com/inhere/php-event-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248826816,"owners_count":21167757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["event","event-management","psr-14"],"created_at":"2024-10-15T06:44:26.206Z","updated_at":"2025-10-30T03:46:01.191Z","avatar_url":"https://github.com/inhere.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Event Dispatcher\n\n[![License](https://img.shields.io/packagist/l/inhere/event.svg?style=flat-square)](LICENSE)\n[![Php Version](https://img.shields.io/badge/php-%3E=7.1.0-brightgreen.svg?maxAge=2592000)](https://packagist.org/packages/inhere/event)\n[![Latest Stable Version](http://img.shields.io/packagist/v/inhere/event.svg)](https://packagist.org/packages/inhere/event)\n\n\u003e **[EN README](./README_en.md)**\n\n简洁, 功能完善的事件管理调度实现\n\n- 实现自 [Psr 14](https://github.com/php-fig/fig-standards/blob/master/proposed/event-dispatcher.md) - 事件调度器\n- 支持对一个事件添加多个监听器\n- 支持设置事件优先级\n- 支持快速的事件组注册\n- 支持根据事件名称来快速的对事件组监听\n  - eg 触发 `app.run`, `app.end` 都将同时会触发 `app.*` 事件\n- 支持通配符事件的监听\n\n## 项目地址\n\n- **github** https://github.com/inhere/php-event-manager.git\n\n## 安装\n\n- composer 命令\n\n```php\ncomposer require inhere/event\n```\n\n- composer.json\n\n```json\n{\n    \"require\": {\n        \"inhere/event\": \"dev-master\"\n    }\n}\n```\n\n### 事件调度器\n\n事件调度器, 也可称之为事件管理器。事件的注册、监听器注册、调度(触发)都是由它管理的。\n\n```php\nuse Inhere\\Event\\EventManager;\n\n$em = new EventManager();\n```\n\n## 事件监听器\n\n监听器允许是: \n\n1. function 函数\n2. 一个闭包\n3. 一个监听器类(可以有多种方式)\n\n### 1. function\n\n```php\n// ... \n\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, 'my_function');\n```\n\n### 2. 闭包\n\n```php\n// ... \n\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, function(Event $event) {\n    // $message = $event-\u003emessage;\n    // ... some logic\n});\n```\n\n### 3. 监听器类(有多种方式)\n\n- 类里面存在跟事件相同名称的方法\n\n\u003e 此种方式可以在类里面写多个事件的处理方法\n\n```php\nclass ExamListener1\n{\n    public function messageSent(EventInterface $event)\n    {\n        echo \"handle the event {$event-\u003egetName()}\\n\";\n    }\n}\n```\n\n- 一个类(含有 `__invoke` 方法)\n\n\u003e 此时这个类对象就相当于一个闭包\n\n```php\nclass ExamListener2\n{\n    public function __invoke(EventInterface $event)\n    {\n        echo \"handle the event {$event-\u003egetName()}\\n\";\n    }\n}\n```\n\n- 实现接口 `EventHandlerInterface`\n\n触发时会自动调用 `handle()` 方法。\n\n```php\nclass ExamHandler implements EventHandlerInterface\n{\n    /**\n     * @param EventInterface $event\n     * @return mixed\n     */\n    public function handle(EventInterface $event)\n    {\n        // TODO: Implement handle() method.\n    }\n}\n```\n\n- 实现接口 `EventSubscriberInterface`\n\n可以在一个类里面自定义监听多个事件\n\n```php\n/**\n * Class EnumGroupListener\n * @package Inhere\\Event\\Examples\n */\nclass EnumGroupListener implements EventSubscriberInterface\n{\n    const TEST_EVENT = 'test';\n    const POST_EVENT = 'post';\n\n    /**\n     * 配置事件与对应的处理方法\n     * @return array\n     */\n    public static function getSubscribedEvents(): array\n    {\n        return [\n            self::TEST_EVENT =\u003e 'onTest',\n            self::POST_EVENT =\u003e ['onPost', ListenerPriority::LOW], // 还可以配置优先级\n        ];\n    }\n\n    public function onTest(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n\n    public function onPost(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n}\n```\n\n## 快速使用\n\n### 1. 绑定事件触发\n\n```php\n// a pre-defined event\nclass MessageEvent extends Event\n{\n    // append property ... \n    public $message;\n}\n\n// in the business\nclass Mailer\n{\n    use EventManagerAwareTrait;\n\n    const EVENT_MESSAGE_SENT = 'messageSent';\n\n    public function send($message)\n    {\n        // ...发送 $message 的逻辑...\n\n        $event = new MessageEvent(self::EVENT_MESSAGE_SENT);\n        $event-\u003emessage = $message;\n        \n        // 事件触发\n        $this-\u003eeventManager-\u003etrigger($event);\n    }\n}\n```\n\n### 2. 触发事件\n\n```php\n$em = new EventManager();\n\n// 绑定事件\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, 'exam_handler');\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, function (EventInterface $event)\n{\n    $pos = __METHOD__;\n    echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n});\n\n// 这里给它设置了更高的优先级\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, new ExamListener1(), 10);\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, new ExamListener2());\n$em-\u003eattach(Mailer::EVENT_MESSAGE_SENT, new ExamHandler());\n\n$mailer = new Mailer();\n$mailer-\u003esetEventManager($em);\n\n// 执行，将会触发事件\n$mailer-\u003esend('hello, world!');\n```\n\n### 3. 运行示例\n\n完整的实例代码在 `examples/demo.php` 中。\n\n运行: `php examples/demo.php`\n\n输出：\n\n```text\n$ php examples/exam.php\nhandle the event 'messageSent' on the: ExamListener1::messageSent // 更高优先级的先调用\nhandle the event 'messageSent' on the: exam_handler\nhandle the event 'messageSent' on the: {closure}\nhandle the event 'messageSent' on the: ExamListener2::__invoke\nhandle the event 'messageSent' on the: Inhere\\Event\\Examples\\ExamHandler::handle\n\n```\n\n## 一组事件的监听器\n\n除了一些特殊的事件外，在一个应用中，大多数事件是有关联的，此时我们就可以对事件进行分组，方便识别和管理使用。\n\n- **事件分组**  推荐将相关的事件，在名称设计上进行分组\n\n例如：\n\n```text\n// 模型相关：\nmodel.insert\nmodel.update\nmodel.delete\n\n// DB相关：\ndb.connect\ndb.disconnect\ndb.query\n\n// 应用相关：\napp.start\napp.run\napp.stop\n```\n\n### 1. 一个简单的示例应用类\n\n```php\n\n/**\n * Class App\n * @package Inhere\\Event\\Examples\n */\nclass App\n{\n    use EventManagerAwareTrait;\n    \n    const ON_START = 'app.start';\n    const ON_STOP = 'app.stop';\n    const ON_BEFORE_REQUEST = 'app.beforeRequest';\n    const ON_AFTER_REQUEST = 'app.afterRequest';\n    \n    public function __construct(EventManager $em)\n    {\n        $this-\u003esetEventManager($em);\n\n        $this-\u003eeventManager-\u003etrigger(new Event(self::ON_START, [\n            'key' =\u003e 'val'\n        ]));\n    }\n\n    public function run()\n    {\n        $sleep = 0;\n        $this-\u003eeventManager-\u003etrigger(self::ON_BEFORE_REQUEST);\n\n        echo 'request handling ';\n        while ($sleep \u003c= 3) {\n            $sleep++;\n            echo '.';\n            sleep(1);\n        }\n        echo \"\\n\";\n\n        $this-\u003eeventManager-\u003etrigger(self::ON_AFTER_REQUEST);\n    }\n\n    public function __destruct()\n    {\n        $this-\u003eeventManager-\u003etrigger(new Event(self::ON_STOP, [\n            'key1' =\u003e 'val1'\n        ]));\n    }\n}\n```\n\n### 2. 此应用的监听器类\n\n将每个事件的监听器写一个类，显得有些麻烦。我们可以只写一个类用里面不同的方法来处理不同的事件。\n\n- 方式一： **类里面存在跟事件名称相同的方法**(`app.start` -\u003e `start()`)\n\n\u003e 这种方式简单快捷，但是有一定的限制 - 事件名与方法的名称必须相同。\n\n```php\n\n/**\n * Class AppListener\n * @package Inhere\\Event\\Examples\n */\nclass AppListener\n{\n    public function start(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n\n    public function beforeRequest(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n\n    public function afterRequest(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n\n    public function stop(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n}\n```\n\n- 方式二：实现接口 `EventSubscriberInterface`\n\n有时候我们并不想将处理方法定义成事件名称一样，想自定义。\n\n此时我们可以实现接口 `EventSubscriberInterface`，通过里面的 `getSubscribedEvents()` 来自定义事件和对应的处理方法\n\n\u003e 运行示例请看 `examples/enum-group.php`\n\n```php\n/**\n * Class EnumGroupListener\n * @package Inhere\\Event\\Examples\n */\nclass EnumGroupListener implements EventSubscriberInterface\n{\n    const TEST_EVENT = 'test';\n    const POST_EVENT = 'post';\n\n    /**\n     * 配置事件与对应的处理方法\n     * @return array\n     */\n    public static function getSubscribedEvents(): array\n    {\n        return [\n            self::TEST_EVENT =\u003e 'onTest',\n            self::POST_EVENT =\u003e ['onPost', ListenerPriority::LOW], // 还可以配置优先级\n        ];\n    }\n\n    public function onTest(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n\n    public function onPost(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event {$event-\u003egetName()} on the: $pos\\n\";\n    }\n}\n\n```\n\n### 3. 添加监听\n\n```php\n// 这里使用 方式一\n$em = new EventManager();\n\n// register a group listener\n$em-\u003eattach('app', new AppListener());\n\n// create app\n$app = new App($em);\n\n// run.\n$app-\u003erun();\n```\n\n### 4. 运行示例\n\n完整的示例代码在 `examples/named-group.php` 中。\n\n运行: `php examples/named-group.php`\n\n输出：\n\n```text\n$ php examples/named-group.php\nhandle the event 'app.start' on the: Inhere\\Event\\Examples\\AppListener::start\nhandle the event 'app.beforeRequest' on the: Inhere\\Event\\Examples\\AppListener::beforeRequest\nrequest handling ....\nhandle the event 'app.afterRequest' on the: Inhere\\Event\\Examples\\AppListener::afterRequest\nhandle the event 'app.stop' on the: Inhere\\Event\\Examples\\AppListener::stop\n\n```\n\n## 事件通配符 `*`\n\n支持使用事件通配符 `*` 对一组相关的事件进行监听, 分两种。\n\n1. `*` 全局的事件通配符。直接对 `*` 添加监听器(`$em-\u003eattach('*', 'global_listener')`), 此时所有触发的事件都会被此监听器接收到。\n2. `{prefix}.*` 指定分组事件的监听。eg `$em-\u003eattach('db.*', 'db_listener')`, 此时所有触发的以 `db.` 为前缀的事件(eg `db.query` `db.connect`)都会被此监听器接收到。\n\n\u003e 当然，你在事件到达监听器前停止了本次事件的传播`$event-\u003estopPropagation(true);`，就不会被后面的监听器接收到了。\n\n示例，在上面的组事件监听器改下，添加一个 `app.*` 的事件监听。\n\n```php\n// AppListener 新增一个方法\nclass AppListener\n{\n    // ...\n\n    public function allEvent(EventInterface $event)\n    {\n        $pos = __METHOD__;\n        echo \"handle the event '{$event-\u003egetName()}' on the: $pos\\n\";\n    }\n}\n\n// ...\n\n$em = new EventManager();\n\n$groupListener = new AppListener();\n\n// register a group listener\n$em-\u003eattach('app', $groupListener);\n\n// all `app.` prefix events will be handled by `AppListener::allEvent()`\n$em-\u003eattach('app.*', [$groupListener, 'allEvent']);\n\n// create app\n$app = new App($em);\n\n// run.\n$app-\u003erun();\n```\n\n### 运行示例\n\n运行: `php examples/named-group.php`\n输出：(_可以看到每个事件都经过了`AppListener::allEvent()`的处理_)\n\n```text\n$ php examples/named-group.php\nhandle the event 'app.start' on the: Inhere\\Event\\Examples\\AppListener::start\nhandle the event 'app.start' on the: Inhere\\Event\\Examples\\AppListener::allEvent\nhandle the event 'app.beforeRequest' on the: Inhere\\Event\\Examples\\AppListener::beforeRequest\nhandle the event 'app.beforeRequest' on the: Inhere\\Event\\Examples\\AppListener::allEvent\nrequest handling ....\nhandle the event 'app.afterRequest' on the: Inhere\\Event\\Examples\\AppListener::afterRequest\nhandle the event 'app.afterRequest' on the: Inhere\\Event\\Examples\\AppListener::allEvent\nhandle the event 'app.stop' on the: Inhere\\Event\\Examples\\AppListener::stop\nhandle the event 'app.stop' on the: Inhere\\Event\\Examples\\AppListener::allEvent\n\n```\n\n## 事件对象\n\n事件对象 - 装载了在触发事件时相关的上下文信息，用户自定义的。\n\n### 预先创建一个事件\n\n- 直接简单的使用类 `Event`\n\n```php\n$myEvent = new Event('name', 'target', [ 'some params ...' ]);\n```\n\n- 使用继承了 `Event` 的子类\n\n这样你可以追加自定义数据\n\n```php\n// create event class\nclass MessageEvent extends Event\n{\n    protected $name = 'messageSent';\n    \n    // append property ... \n    public $message;\n}\n\n```\n\n## License \n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finhere%2Fphp-event-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finhere%2Fphp-event-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finhere%2Fphp-event-manager/lists"}