能夠替代數據庫的觸發器功能。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
提供了觀察者在啓動過程的加載服務。