简介
可以替代数据库的触发器功能。
Observer
的创建
观察者的功能来自与继承的 Model
对象的 trait HasEvents
特质。
本章我们使用 Laravel
默认的 User
模型来进行说明。
创建一个观察者类
注册 Observer
类
通过 provider
来注册 Observer
关于
provider
加载机制可以移步【Laravel-海贼王系列】第八章, Provider 功能解析
观察过程解析
User::observe()
方法来自 Illuminate\Database\Eloquent\Concerns\HasEvents;
上面介绍过了,这个特质类是关键,我也主要围绕这个类来分析。
public static function observe($classes)
{
// "指向 User 对象"
$instance = new static;
// "支持一次传入数组或者字符串的型式统一包装成数组"
// "这里可以看出 observe() 方法支持一次观察多个类"
foreach (Arr::wrap($classes) as $class) {
$instance->registerObserver($class);
}
}
展开 $instance->registerObserver($class)
;
// "刚才的传入 $class = 'App\UserObserver'"
protected function registerObserver($class)
{
$className = is_string($class) ? $class : get_class($class);
// "这里就是获取指定的事件名称"
$this->getObservableEvents() = array_merge(
[
'retrieved', 'creating', 'created', 'updating', 'updated',
'saving', 'saved', 'restoring', 'restored',
'deleting', 'deleted', 'forceDeleted',
],
$this->observables, // "这个是提供给用户自己定义的方法"
);
foreach ($this->getObservableEvents() as $event) {
// "还记得 'App\UserObserver' 中定义的方法吗!"
if (method_exists($class, $event)) {
static::registerModelEvent($event, $className.'@'.$event);
}
}
}
注册 Observer
中的事件
上面循环了所有的提前指定事件,然后逐个检查观察者并进行注册。
继续分析 static::registerModelEvent($event, $className.'@'.$event);
protected static function registerModelEvent($event, $callback)
{
if (isset(static::$dispatcher)) {
$name = static::class;
static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
}
}
statci::$dispatcher
是 lluminate\Events\Dispatcher
对象
所以其实这里迭代调用了,可以看到就是绑定一个个事件,同时将事件
指向UserObserver@functionName
的对应方法中。
static::$dispatcher->listen("eloquent.retrieved: App\User", 'App\UserObserver@retrieved');
static::$dispatcher->listen("eloquent.creating: App\User", 'App\UserObserver@creating');
static::$dispatcher->listen("eloquent.created: App\User", 'App\UserObserver@created');
..... 省略类似代码
static::$dispatcher->listen("eloquent.forceDeleted: App\User", 'App\UserObserver@forceDeleted');
关于事件的绑定以及触发机制请移步【Laravel-海贼王系列】第九章, Events 功能解析
经历过上面种种绑定我们已经绑定了需要的事件,并且监听者就是 UserObserver
对象。
接下来就是如何触发的问题了。
触发 Observer
监听的事件
我们来看常用的生成用户的方法。
User::create(
[
'name' => "big pig's feet",
'email' => 'hello@world.com',
'password' => password_hash('123456', PASSWORD_BCRYPT, ['cost' => 12,]),
]
);
⚠️这里
create
方法在Model
中并不存在,会调用魔术方法__call()
我们本章只关心观察者,查询构建器后续在涉及!直接看最终调用方法
位于 Model
的 performInsert
方法
protected function performInsert(Builder $query)
{
if ($this->fireModelEvent('creating') === false) {
return false;
}
if ($this->usesTimestamps()) {
$this->updateTimestamps();
}
$attributes = $this->getAttributes();
if ($this->getIncrementing()) {
$this->insertAndSetId($query, $attributes);
}else {
if (empty($attributes)) {
return true;
}
$query->insert($attributes);
}
$this->exists = true;
$this->wasRecentlyCreated = true;
$this->fireModelEvent('created', false);
return true;
}
这里我们不详解如何执行事件的代码,我们只关心执行了什么!
执行逻辑分析:
首先触发模型之前绑定的
creating
方法。
调用最后插入数据的逻辑。
设置一些放重复的属性
调用绑定的
created
事件。
到了这里可以知道官方给出的许多事件以及执行顺序的原因!
结语
Laravel
的 Model
功能非常多,本章只是
简单的介绍了其中一种功能“观察者”,还有很多方法没有分析
但是基本原理我们只要知道一种其他也都是一样。
最后总结一下
Model
结合laravel
事件来完成观察者事件的监听和触发。
Provider
提供了观察者在启动过程的加载服务。