# 事件 模型事件實現 [psr/event-dispatcher](https://github.com/php-fig/event-dispatcher) 接口,默認由 [hyperf/event](https://github.com/hyperf/event) 組件提供功能支持。 ## 運行事件 在 ORM 的運行期間,會對應觸發以下事件,您可以進行對這些事件進行監聽以滿足您的需求。 | 事件 | 描述 | | :--------: | :----: | | Hyperf\Database\Events\QueryExecuted| Query 語句執行後 | | Hyperf\Database\Events\StatementPrepared| SQL 語句 prepared 後 | | Hyperf\Database\Events\TransactionBeginning| 事務開啓後 | | Hyperf\Database\Events\TransactionCommitted| 事務提交後 | | Hyperf\Database\Events\TransactionRolledBack| 事務回滾後 | ### SQL 執行監聽器 根據上述的 ORM 運行事件,接下來我們來實現一個記錄 SQL 的監聽器,達到在每次執行 SQL 時記錄下來並輸出到日誌上。 首先我們定義好 `DbQueryExecutedListener` ,實現 `Hyperf\Event\Contract\ListenerInterface` 接口並對類定義 `Hyperf\Event\Annotation\Listener` 註解,這樣 Hyperf 就會在應用啓動時自動把該監聽器註冊到事件調度器中,並在事件觸發時執行監聽邏輯,示例代碼如下: ```php logger = $container->get(LoggerFactory::class)->get('sql'); } public function listen(): array { return [ QueryExecuted::class, ]; } /** * @param QueryExecuted $event */ public function process(object $event) { if ($event instanceof QueryExecuted) { $sql = $event->sql; if (! Arr::isAssoc($event->bindings)) { foreach ($event->bindings as $key => $value) { $sql = Str::replaceFirst('?', "'{$value}'", $sql); } } $this->logger->info(sprintf('[%s] %s', $event->time, $sql)); } } } ``` ## 模型事件 模型事件與 `Eloquent ORM` 不太一致,`Eloquent ORM` 使用 `Observer` 監聽模型事件。`Hyperf` 提供 `鈎子函數` 和 `事件監聽` 兩種形式來處理對應的事件。 ### 鈎子函數 | 事件名 | 觸發實際 | 是否阻斷 | 備註 | |:------------:|:----------------:|:--------:|:-------------------------- --:| | booting | 模型首次加載前 | 否 | 進程生命週期中只會觸發一次 | | booted | 模型首次加載後 | 否 | 進程生命週期中只會觸發一次 | | retrieved | 填充數據後 | 否 | 每當模型從 DB 或緩存查詢出來後觸發 | | creating | 數據創建時 | 是 | | | created | 數據創建後 | 否 | | | updating | 數據更新時 | 是 | | | updated | 數據更新後 | 否 | | | saving | 數據創建或更新時 | 是 | | | saved | 數據創建或更新後 | 否 | | | restoring | 軟刪除數據恢復時 | 是 | | | restored | 軟刪除數據恢復後 | 否 | | | deleting | 數據刪除時 | 是 | | | deleted | 數據刪除後 | 否 | | | forceDeleting | 數據強制刪除時 | 是 | | | forceDeleted | 數據強制刪除後 | 否 | | 針對某個模型的事件使用十分簡單,只需要在模型中增加對應的方法即可。例如下方保存數據時,觸發 `saving` 事件,主動覆寫 `created_at` 字段。 ```php 'integer', 'gender' => 'integer']; public function saving(Saving $event) { $this->setCreatedAt('2019-01-01'); } } ``` ### 事件監聽 當您需要監聽所有的模型事件時,可以很方便的自定義對應的 `Listener`,比如下方模型緩存的監聽器,當模型修改和刪除後,會刪除對應緩存。 ```php getModel(); if ($model instanceof CacheableInterface) { $model->deleteCache(); } } } } ```