如果你是透過 Eloquent 操作資料庫 CRUD,當你對資料做增刪時會自動觸發相關的 Event Hook,例如 Insert 前觸發 creating
Hook、Insert 後會觸發 created
Hook。想知道總共有哪些 Hook 可以看官網。
Event Hook 最常被用到的地方是 Relation data delete/update Cascade,也就是假如一個使用者被刪除,他過去的文章也要一併被刪除 — 我們稱做「關聯刪除」。Laravel 預設不會幫我們做關聯刪除,這種時候就很適合在 deleting
Hook 裡註冊一個 Article delete event。(見下方範例)
// in App\\Models\\User.php
class User
{
// ...
/**
* 先建立 User 跟 Article 之間的關聯
*/
public function articles()
{
return $this->hasMany(Article::class);
}
public static function boot()
{
parent::boot();
/**
* 針對 deleting event hook 註冊關聯刪除
*/
static::deleting(function (User $user) {
$user->articles->each(function ($article) {
$article->delete();
});
});
}
}
除了關聯資料刪除,也可以做關聯更新,也就是 Hook 裡撰寫一般的 Eloquent 操作。例如你有一個表格 factory_counts
,用以紀錄工廠底下所有倉庫的貨存量,如果有一個倉庫被刪除,貨存量就要減去該倉庫的擁有數。
// in App\\Models\\Storehouse.php
/* 倉庫 */
class Storehouse
{
/* 倉庫所存的商品 */
public function Goods()
{
return $this->hasMany(Goods::class);
}
/* 當倉庫被刪除時減去貨存量 */
public static function boot()
{
static::deleting(function (Storehouse $store) {
$goodsNum = $store->goods()->count();
Factory::where('id', $store->factory_id)->decrement('counts', $goodsNum);
});
}
}
deleting
Event!問題描述:我執行了 User 的刪除,但卻沒有觸發 User 的 deleting Hook。
這是一個非常常見的問題。
通常發生原因為:你實際只是操作了 SQL Query,並沒有真的透過 Eloquent 獲取 instance,對它進行操作,所以 Hook 沒有觸發。
例如你刪除的指令通常都這樣寫:
Factory::where('id', $id)->delete();
這行動作只是執行了 SQL Query,並沒有真的獲取一個 Query Result Collection/Object。只有對一個實際 Query 出的 instance 進行操作才會觸發 Hook。