能够替代数据库的触发器功能。laravel
Observer
的建立观察者的功能来自与继承的 Model
对象的 trait HasEvents
特质。数据库
本章咱们使用 Laravel
默认的 User
模型来进行说明。数组
建立一个观察者类bash
Observer
类经过 provider
来注册 Observer
ide
关于
provider
加载机制能够移步【Laravel-海贼王系列】第八章, Provider 功能解析post
User::observe()
方法来自 Illuminate\Database\Eloquent\Concerns\HasEvents;
ui
上面介绍过了,这个特质类是关键,我也主要围绕这个类来分析。this
public static function observe($classes)
{
// "指向 User 对象"
$instance = new static;
// "支持一次传入数组或者字符串的型式统一包装成数组"
// "这里能够看出 observe() 方法支持一次观察多个类"
foreach (Arr::wrap($classes) as $class) {
$instance->registerObserver($class);
}
}
复制代码
展开 $instance->registerObserver($class)
;spa
// "刚才的传入 $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
中的事件上面循环了全部的提早指定事件,而后逐个检查观察者并进行注册。rest
继续分析 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
提供了观察者在启动过程的加载服务。