事件驅動程式設計是一種程式設計模式,其中的程式流由諸如使用者動作(滑鼠點選,按鍵)、感測器輸出或來自其他程式/執行緒的訊息等事件來決定確定。事件驅動程式設計是圖形使用者介面和其他應用程式(例如 JavaScript Web 應用程式)中使用的主要範例,用於執行某些操作來響應使用者輸入。
在 Laravel 裡,有些事件是由她自動發起的,例如 Model 的 create、save、 update 或者是 delete 操作時,她會分別發起相應的事件,如果我們需要,可以監聽這些事件,完成不同的需求。除了她自動發起的事件,我們也可以自己定義我們需要的事件以及監聽器。
在應用中使用事件,是解耦應用的好方法,比如註冊一位新使用者。
Class UserController extends Controller
{
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
...
...
]);
$user = User::create($request->all());
// 歡迎郵件
if ($user->email) {
Mail::to($user->email)->send(new Email($user));
}
// 推薦註冊邏輯
if ($request->get('invite_code')) {
...
...
}
// 通知運營
$user->notify(new NewUser($user));
// 各種各樣的需求
...
...
return Auth::login($user);
}
}
在這個使用者註冊方法中,耦合了各種各樣的邏輯,各種各樣的需求,如果還要加一些奇怪的需求,這個方法就會越來越大,越來越長。
方法的關注點應該只有註冊使用者到應用中,它不應該關心其他邏輯。
這裡我們通過 Laravel 的 artisan 命令,建立我們需要的事件類和與之對應的監聽類。
php artisan make:event UserRegistered
php artisan make:listener SendWelcomeMail --event=UserRegistered
php artisan make:listener UpdateReferrer --event=UserRegistered
接下來,不要忘記到 EventServiceProvider 裡的 $listen 屬性中註冊事件與監聽器。
protected $listen = [
UserRegistered::class => [
SendWelcomeMail::class,
UpdateReferrer::class,
]
];
開啟 app/Events/UserRegistered.php
public $user;
public function __construct(User $user)
{
$this->user = $user;
}
接著開啟 SendWelcomeMail.php
public function handle(UserRegistered $event)
{
if (!$event->user->email) {
return;
}
Mail::to($event->user->email)->send(new Email($event->user));
}
再開啟 UpdateReferrer.php
public function handle(UserRegistered $event)
{
...
...
}
可以看到,通過事件驅動,我們讓 UserController 的 store 方法,變得儘可能的少,並且專注於註冊使用者這件事上,其他邏輯由 UserRegistered 事件的監聽器來負責完成。如果有新增加的需求,可是建立一個新的監聽器來完成這件事。
當完成了事件與監聽器的編寫與註冊之後,我們可以把它放進控制器邏輯。
public function store(Request $request)
{
...
...
...
\event(new UserRegistered($user));
}
我個人比較喜歡把它放在模型事件中觸發,可以嘗試這麼寫。
class User extends Model
{
public static function boot()
{
parent::boot();
static::created(function (User $user) {
\event(new UserRegistered($user));
});
}
}
我覺得使用 Laravel 的事件系統,可以讓我們的作品變得更優雅,邏輯條理更清晰,也更具有擴充性。讓每部分程式碼塊,都知道自己是幹什麼的,要幹什麼,不需要關注與自己無關的事兒。程式碼塊之間分工合作,你中有我,我中有你,最終把這件事情完成好。