2019-03-19 14:03:48 +08:00
|
|
|
|
# 事件
|
2019-03-21 16:25:20 +08:00
|
|
|
|
模型事件实现于 [psr/event-dispatcher](https://github.com/php-fig/event-dispatcher) 接口。
|
2019-03-19 14:03:48 +08:00
|
|
|
|
|
|
|
|
|
## 自定义监听器
|
2019-05-22 13:24:23 +08:00
|
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
|
得益于 [hyperf/event](https://github.com/hyperf-cloud/event) 组件的支撑,用户可以很方便的对以下事件进行监听。
|
2019-03-21 16:22:34 +08:00
|
|
|
|
例如 `QueryExecuted` , `StatementPrepared` , `TransactionBeginning` , `TransactionCommitted` , `TransactionRolledBack` 。
|
2019-12-12 16:24:04 +08:00
|
|
|
|
接下来我们就实现一个记录SQL的监听器,来说一下怎么使用。
|
2019-03-21 16:22:34 +08:00
|
|
|
|
首先我们定义好 `DbQueryExecutedListener` ,实现 `Hyperf\Event\Contract\ListenerInterface` 接口并对类定义 `Hyperf\Event\Annotation\Listener` 注解,这样 Hyperf 就会自动把该监听器注册到事件调度器中,无需任何手动配置,示例代码如下:
|
2019-03-19 14:03:48 +08:00
|
|
|
|
|
2019-03-19 14:52:21 +08:00
|
|
|
|
```php
|
2019-03-19 14:03:48 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace App\Listeners;
|
|
|
|
|
|
2019-03-21 16:22:34 +08:00
|
|
|
|
use Hyperf\Database\Events\QueryExecuted;
|
|
|
|
|
use Hyperf\Event\Annotation\Listener;
|
|
|
|
|
use Hyperf\Event\Contract\ListenerInterface;
|
|
|
|
|
use Hyperf\Logger\LoggerFactory;
|
2019-03-19 14:03:48 +08:00
|
|
|
|
use Hyperf\Utils\Arr;
|
|
|
|
|
use Hyperf\Utils\Str;
|
|
|
|
|
use Psr\Container\ContainerInterface;
|
2019-03-21 16:22:34 +08:00
|
|
|
|
use Psr\Log\LoggerInterface;
|
2019-03-19 14:03:48 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Listener
|
|
|
|
|
*/
|
|
|
|
|
class DbQueryExecutedListener implements ListenerInterface
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* @var LoggerInterface
|
|
|
|
|
*/
|
|
|
|
|
private $logger;
|
|
|
|
|
|
2019-03-21 16:22:34 +08:00
|
|
|
|
public function __construct(LoggerFactory $loggerFactory)
|
2019-03-19 14:03:48 +08:00
|
|
|
|
{
|
2019-03-21 16:22:34 +08:00
|
|
|
|
$this->logger = $loggerFactory->get('sql');
|
2019-03-19 14:03:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 14:52:21 +08:00
|
|
|
|
```
|
2019-03-19 14:03:48 +08:00
|
|
|
|
|
|
|
|
|
## 模型事件
|
2019-03-21 13:17:51 +08:00
|
|
|
|
|
2019-12-12 16:24:04 +08:00
|
|
|
|
模型事件与 `EloquentORM` 不太一致,`EloquentORM` 使用 `Observer` 监听模型事件。`Hyperf` 直接使用 `钩子函数` 来处理对应的事件。如果你还是喜欢 `Observer` 的方式,可以通过 `事件监听`,自己实现。当然,你也可以在 [issue#2](https://github.com/hyperf-cloud/hyperf/issues/2) 下面告诉我们。
|
2019-05-22 13:24:23 +08:00
|
|
|
|
|
|
|
|
|
### 钩子函数
|
|
|
|
|
|
2019-03-25 19:00:55 +08:00
|
|
|
|
| 事件名 | 触发实际 | 是否阻断 | 备注 |
|
|
|
|
|
|:------------:|:----------------:|:--------:|:-------------------------- --:|
|
|
|
|
|
| booting | 模型首次加载前 | 否 | 进程生命周期中只会触发一次 |
|
|
|
|
|
| booted | 模型首次加载后 | 否 | 进程生命周期中只会触发一次 |
|
2019-12-12 16:24:04 +08:00
|
|
|
|
| retrieved | 填充数据后 | 否 | 每当模型从DB或缓存查询出来后触发 |
|
2019-03-25 19:00:55 +08:00
|
|
|
|
| creating | 数据创建时 | 是 | |
|
|
|
|
|
| created | 数据创建后 | 否 | |
|
|
|
|
|
| updating | 数据更新时 | 是 | |
|
|
|
|
|
| updated | 数据更新后 | 否 | |
|
2019-03-21 13:17:51 +08:00
|
|
|
|
| saving | 数据创建或更新时 | 是 | |
|
|
|
|
|
| saved | 数据创建或更新后 | 否 | |
|
|
|
|
|
| restoring | 软删除数据回复时 | 是 | |
|
|
|
|
|
| restored | 软删除数据回复后 | 否 | |
|
2019-03-25 19:00:55 +08:00
|
|
|
|
| deleting | 数据删除时 | 是 | |
|
|
|
|
|
| deleted | 数据删除后 | 否 | |
|
2019-03-21 13:17:51 +08:00
|
|
|
|
| forceDeleted | 数据强制删除后 | 否 | |
|
|
|
|
|
|
2019-05-22 13:24:23 +08:00
|
|
|
|
针对某个模型的事件使用十分简单,只需要在模型中增加对应的方法即可。例如下方保存数据时,触发 `saving` 事件,主动覆写 `created_at` 字段。
|
2019-03-21 13:17:51 +08:00
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
use Hyperf\Database\Model\Events\Saving;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @property $id
|
|
|
|
|
* @property $name
|
2019-03-21 16:22:34 +08:00
|
|
|
|
* @property $gender
|
2019-03-21 13:17:51 +08:00
|
|
|
|
* @property $created_at
|
|
|
|
|
* @property $updated_at
|
|
|
|
|
*/
|
|
|
|
|
class User extends Model
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* The table associated with the model.
|
|
|
|
|
*
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
protected $table = 'user';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The attributes that are mass assignable.
|
|
|
|
|
*
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
2019-03-21 16:22:34 +08:00
|
|
|
|
protected $fillable = ['id', 'name', 'gender', 'created_at', 'updated_at'];
|
2019-03-21 13:17:51 +08:00
|
|
|
|
|
2019-03-21 16:22:34 +08:00
|
|
|
|
protected $casts = ['id' => 'integer', 'gender' => 'integer'];
|
2019-03-21 13:17:51 +08:00
|
|
|
|
|
|
|
|
|
public function saving(Saving $event)
|
|
|
|
|
{
|
|
|
|
|
$this->setCreatedAt('2019-01-01');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 13:24:23 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 事件监听
|
|
|
|
|
|
|
|
|
|
当你需要监听所有的模型事件时,可以很方便的自定义对应的 `Listener`,比如下方模型缓存的监听器,当模型修改和删除后,会删除对应缓存。
|
|
|
|
|
|
|
|
|
|
```php
|
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace Hyperf\ModelCache\Listener;
|
|
|
|
|
|
|
|
|
|
use Hyperf\Database\Model\Events\Deleted;
|
|
|
|
|
use Hyperf\Database\Model\Events\Event;
|
|
|
|
|
use Hyperf\Database\Model\Events\Saved;
|
|
|
|
|
use Hyperf\Event\Annotation\Listener;
|
|
|
|
|
use Hyperf\Event\Contract\ListenerInterface;
|
|
|
|
|
use Hyperf\ModelCache\CacheableInterface;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Listener
|
|
|
|
|
*/
|
|
|
|
|
class DeleteCacheListener implements ListenerInterface
|
|
|
|
|
{
|
|
|
|
|
public function listen(): array
|
|
|
|
|
{
|
|
|
|
|
return [
|
|
|
|
|
Deleted::class,
|
|
|
|
|
Saved::class,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function process(object $event)
|
|
|
|
|
{
|
|
|
|
|
if ($event instanceof Event) {
|
|
|
|
|
$model = $event->getModel();
|
|
|
|
|
if ($model instanceof CacheableInterface) {
|
|
|
|
|
$model->deleteCache();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-21 13:17:51 +08:00
|
|
|
|
```
|