事件

模型事件实现于 psr/event-dispatcher 接口。

自定义监听器

得益于 hyperf/event 组件的支撑,用户可以很方便的对以下事件进行监听。例如 QueryExecuted , StatementPrepared , TransactionBeginning , TransactionCommitted , TransactionRolledBack 。接下来我们就实现一个记录SQL的监听器,来说一下怎么使用。首先我们定义好 DbQueryExecutedListener ,实现 Hyperf\Event\Contract\ListenerInterface 接口并对类定义 Hyperf\Event\Annotation\Listener 注解,这样 Hyperf 就会自动把该监听器注册到事件调度器中,无需任何手动配置,示例代码如下:

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Listeners;
  4. use Hyperf\Database\Events\QueryExecuted;
  5. use Hyperf\Event\Annotation\Listener;
  6. use Hyperf\Event\Contract\ListenerInterface;
  7. use Hyperf\Logger\LoggerFactory;
  8. use Hyperf\Utils\Arr;
  9. use Hyperf\Utils\Str;
  10. use Psr\Container\ContainerInterface;
  11. use Psr\Log\LoggerInterface;
  12. /**
  13. * @Listener
  14. */
  15. class DbQueryExecutedListener implements ListenerInterface
  16. {
  17. /**
  18. * @var LoggerInterface
  19. */
  20. private $logger;
  21. public function __construct(LoggerFactory $loggerFactory)
  22. {
  23. $this->logger = $loggerFactory->get('sql');
  24. }
  25. public function listen(): array
  26. {
  27. return [
  28. QueryExecuted::class,
  29. ];
  30. }
  31. /**
  32. * @param QueryExecuted $event
  33. */
  34. public function process(object $event)
  35. {
  36. if ($event instanceof QueryExecuted) {
  37. $sql = $event->sql;
  38. if (! Arr::isAssoc($event->bindings)) {
  39. foreach ($event->bindings as $key => $value) {
  40. $sql = Str::replaceFirst('?', "'{$value}'", $sql);
  41. }
  42. }
  43. $this->logger->info(sprintf('[%s] %s', $event->time, $sql));
  44. }
  45. }
  46. }

模型事件

模型事件与 EloquentORM 不太一致,EloquentORM 使用 Observer 监听模型事件。Hyperf 直接使用 钩子函数 来处理对应的事件。如果你还是喜欢 Observer 的方式,可以通过 事件监听,自己实现。当然,你也可以在 issue#2 下面告诉我们。

钩子函数

事件名触发实际是否阻断备注
booting模型首次加载前进程生命周期中只会触发一次
booted模型首次加载后进程生命周期中只会触发一次
retrieved填充数据后每当模型从DB或缓存查询出来后触发
creating数据创建时
created数据创建后
updating数据更新时
updated数据更新后
saving数据创建或更新时
saved数据创建或更新后
restoring软删除数据回复时
restored软删除数据回复后
deleting数据删除时
deleted数据删除后
forceDeleted数据强制删除后

针对某个模型的事件使用十分简单,只需要在模型中增加对应的方法即可。例如下方保存数据时,触发 saving 事件,主动覆写 created_at 字段。

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Models;
  4. use Hyperf\Database\Model\Events\Saving;
  5. /**
  6. * @property $id
  7. * @property $name
  8. * @property $gender
  9. * @property $created_at
  10. * @property $updated_at
  11. */
  12. class User extends Model
  13. {
  14. /**
  15. * The table associated with the model.
  16. *
  17. * @var string
  18. */
  19. protected $table = 'user';
  20. /**
  21. * The attributes that are mass assignable.
  22. *
  23. * @var array
  24. */
  25. protected $fillable = ['id', 'name', 'gender', 'created_at', 'updated_at'];
  26. protected $casts = ['id' => 'integer', 'gender' => 'integer'];
  27. public function saving(Saving $event)
  28. {
  29. $this->setCreatedAt('2019-01-01');
  30. }
  31. }

事件监听

当你需要监听所有的模型事件时,可以很方便的自定义对应的 Listener,比如下方模型缓存的监听器,当模型修改和删除后,会删除对应缓存。

  1. <?php
  2. declare(strict_types=1);
  3. namespace Hyperf\ModelCache\Listener;
  4. use Hyperf\Database\Model\Events\Deleted;
  5. use Hyperf\Database\Model\Events\Event;
  6. use Hyperf\Database\Model\Events\Saved;
  7. use Hyperf\Event\Annotation\Listener;
  8. use Hyperf\Event\Contract\ListenerInterface;
  9. use Hyperf\ModelCache\CacheableInterface;
  10. /**
  11. * @Listener
  12. */
  13. class DeleteCacheListener implements ListenerInterface
  14. {
  15. public function listen(): array
  16. {
  17. return [
  18. Deleted::class,
  19. Saved::class,
  20. ];
  21. }
  22. public function process(object $event)
  23. {
  24. if ($event instanceof Event) {
  25. $model = $event->getModel();
  26. if ($model instanceof CacheableInterface) {
  27. $model->deleteCache();
  28. }
  29. }
  30. }
  31. }