Laravel 模型事件與事件監聽系統
Observer(模型觀察者)
📌 目的
Observer 是 Laravel 提供的一種設計模式,用來監聽 Eloquent 模型的生命週期事件(如
creating、created、updating、updated、deleting、deleted、saving、retrieved
等),並在這些事件發生時執行對應邏輯。
⚙️ 原理
- Observer 是綁定於某個 Eloquent 模型的類別。
- Observer 中的方法名稱對應模型的事件名稱,例如:
created(User $user):模型資料建立後觸發
updated(User $user):模型資料更新後觸發
- 這些事件會自動呼叫 Observer 中對應的方法。
✅ 使用範例
✅ 建議將觀察者註冊寫在服務提供者中,避免模型中混合過多邏輯。
Listener(事件監聽器)
📌 目的
Listener 是 Laravel 事件系統的一部分,透過手動觸發事件並由對應的 Listener 處理後續邏輯,可達到業務邏輯的解耦與模組化。
⚙️ 原理
- 使用
event() 或 dispatch() 方法觸發事件。
- 系統會自動呼叫與該事件對應的所有 Listener 並執行其
handle() 方法。
- 適合處理與資料庫無直接綁定的業務邏輯(如:發送通知、寄信、寫入第三方)。
✅ 使用範例
✅ 事件與 Listener 可用 php artisan event:generate 批次生成。
Observer vs Listener 比較
| 項目 |
Observer |
Listener |
| 觸發時機 |
綁定 Eloquent 模型事件 |
手動觸發自定義事件 |
| 用途 |
監聽模型 CRUD 行為、自動邏輯處理 |
解耦模組邏輯、背景處理 |
| 適用設計模式 |
Observer Pattern |
Event-Listener Pattern |
| 註冊方式 |
模型內 observe() |
EventServiceProvider 中註冊 |
| 常見用途 |
寫入 log、更新統計、通知 |
寄信、非同步處理、通知、觸發工作任務等 |
多對多與多型多對多關聯的事件監聽
🧩 策略建議
使用自訂 Pivot 模型
使用自訂 MorphPivot 模型(多型多對多)
🔗 官方文件連結
Laravel 模型事件與事件監聽系統
Observer(模型觀察者)
📌 目的
Observer 是 Laravel 提供的一種設計模式,用來監聽 Eloquent 模型的生命週期事件(如
creating、created、updating、updated、deleting、deleted、saving、retrieved等),並在這些事件發生時執行對應邏輯。⚙️ 原理
created(User $user):模型資料建立後觸發updated(User $user):模型資料更新後觸發✅ 使用範例
# 建立 Observer 類別 php artisan make:observer UserObserver --model=User// app/Observers/UserObserver.php use App\Models\User; use Illuminate\Support\Facades\Log; class UserObserver { public function created(User $user) { Log::info('新使用者已建立:' . $user->name); } }// AppServiceProvider 或專屬服務提供者中註冊 use App\Models\User; use App\Observers\UserObserver; public function boot() { User::observe(UserObserver::class); }Listener(事件監聽器)
📌 目的
Listener 是 Laravel 事件系統的一部分,透過手動觸發事件並由對應的 Listener 處理後續邏輯,可達到業務邏輯的解耦與模組化。
⚙️ 原理
event()或dispatch()方法觸發事件。handle()方法。✅ 使用範例
# 建立事件與對應的監聽器 php artisan make:event OrderShipped php artisan make:listener SendShipmentNotification --event=OrderShipped// 在程式中觸發事件 event(new OrderShipped($order));// app/Listeners/SendShipmentNotification.php use App\Events\OrderShipped; use Illuminate\Support\Facades\Mail; class SendShipmentNotification { public function handle(OrderShipped $event) { Mail::to($event->order->user)->send(/* ... */); } }// EventServiceProvider 中註冊 protected $listen = [ \App\Events\OrderShipped::class => [ \App\Listeners\SendShipmentNotification::class, ], ];Observer vs Listener 比較
多對多與多型多對多關聯的事件監聽
🧩 策略建議
想要「自動監聽多對多關聯變化」:
想要「明確控制邏輯觸發點」:
多型關聯(polymorphic)亦可搭配
MorphPivot模型處理。使用自訂 Pivot 模型
// 定義自訂 Pivot 模型(需繼承 Illuminate\Database\Eloquent\Relations\Pivot) use Illuminate\Database\Eloquent\Relations\Pivot; class RoleUser extends Pivot { protected static function booted() { static::created(function ($pivot) { Log::info("角色已新增至使用者", [ 'user_id' => $pivot->user_id, 'role_id' => $pivot->role_id, ]); }); } }// 在模型的 belongsToMany 關聯中指定 using() public function roles() { return $this->belongsToMany(Role::class)->using(RoleUser::class); }使用自訂 MorphPivot 模型(多型多對多)
use Illuminate\Database\Eloquent\Relations\MorphPivot; class Taggable extends MorphPivot { protected static function booted() { static::created(function ($pivot) { Log::info("標籤已新增", $pivot->toArray()); }); } }// 在 morphToMany 關聯中使用 using() public function tags() { return $this->morphToMany(Tag::class, 'taggable')->using(Taggable::class); }🔗 官方文件連結