# 前言
學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法
; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣造一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。
# Registering Events & Listeners
以下位於 EventServiceProvider 的 Laravel example code 的意思是?
- Example:
<?php
protected $listen = [
'App\Events\OrderShipped' => [
'App\Listeners\SendShipmentNotification',
],
]; - Answer:
在 EventServiceProvider 的 $listen property 中
註冊一個 Listener SendShipmentNotification 監聽 OrderShipped event
# Generating Events & Listeners
Laravel 中, 我先在 EventServiceProvider 的 $listen protected property 定義好 event 跟 listener 之後, 怎麼使用 CLI 讓定義好的 event 跟 listener 自動產生?
php artisan event:generate |
# Manually Registering Events
Laravel 中, 如果我想要定義 closure based event, 我可以在哪一個檔案中定義?
EventServiceProvider
Laravel 中, 如果我想要定義 closure based event, 我可以在 EventServiceProvider 中的 哪一個 method 中定義?
boot method
以下的 Laravel example code 的意思是?
- Example:
<?php
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
} - Answer:
在 EventServiceProvider 的 boot method 定義 closure based event, 第一個 argument 為該 event name, closure 內為 trigger event 時要做的事, 相當於定義於 Listener 中的邏輯
# Wild Event Listeners
以下的 Laravel example code 的意思是?
- Example:
<?php
Event::listen('registered.*', function ($eventName, array $data) {
//
}); - Answer:
監聽所有registered.
開頭的 event
以下的 Laravel example code 的意思是?
- Example:
<?php
Event::listen('event.*', function ($eventName, array $data) {
//
}); - Answer:
監聽 wildcard event, 第一個 argument 為 event name, 第二個為該 event 的 data
# Event Discovery
Laravel Event 中, Event Discovery 的規則, 會 scan 哪一個資料夾中的 Listeners?
Listeners directory
Laravel Event 中, Event Discovery 的規則, 假設以下的 Listener 為我 scan 到的 Listener, Laravel 會將這個 Listener 註冊給哪一個 event?
- Example:
<?php
use App\Events\PodcastProcessed;
class SendPodcastProcessedNotification
{
public function handle(PodcastProcessed $event)
{
//
}
} - Answer:
PodcastProcessed event
Laravel Event 中, Event Discovery 的規則, 預設是關閉的還是打開的?
關閉的
以下的 Laravel example code 的意思是?
- Example:
<?php
public function shouldDiscoverEvents()
{
return true;
} - Answer:
Laravel 預設關閉 Event Discovery, 就是會根據 convention 將 listener 註冊給 listener handle method 中 type hint 的 event class
若要開啟, 可在 EventServiceProvider 的 shouldDiscoverEvents() 中開啟
以下位於 EventServiceProvider 的 Laravel example code 的意思是?
- Example:
<?php
protected function discoverEventsWithin()
{
return [
$this->app->path('Listeners'),
];
} - Answer:
若有開啟 Event Discovery, 預設會掃描 ‘app/Listeners’ 資料夾內的 events, 若要變更資料夾位置, 可在 discoverEventsWithin() 中定義
Laravel production 環境中, 我們可能不想要框架在每一個 request 都去 scan 所有的 listeners, 可以使用哪一個 CLI 來將 events 以及 listeners cache 住?
php artisan event:cache |
Laravel production 環境中, 我們可能不想要框架在每一個 request 都去 scan 所有的 listeners, 所以使用 CLI 來 cache events 以及 listeners, 如果我要將 cache 拿掉, 可以使用哪一個 CLI?
php artisan event:clear |
Laravel 中, 如果我想要使用 CLI 來顯示所有 events 以及 listeners 的對應關係, 可以使用哪一個 CLI?
php artisan event:list |
# Defining Events
Laravel Event 中, 會寫到邏輯嗎?
不會哦
# Defining Listeners
# Stopping The Propagation Of An Event
Laravel 中, 如果我想要停止某個 listener 對某個 event 的傳播, 那我可以在該 listener 的 handle method 中回傳什麼?
false
# Queued Event Listeners
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
//
} - Answer:
將 listener class implement ShouldQueue interface, 當觸發該 listener 時, 該 job 會被 queue
# Customizing The Queue Connection & Queue Name
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
public $connection = 'sqs';
} - Answer:
在 listener class 當中指定 connection 為 ‘sqs’
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
public $queue = 'listeners';
} - Answer:
在 listener class 中使用 $queue 指定該 listener 使用的 queue
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
public $delay = 60;
} - Answer:
在 listener class 中, 使用 $delay 定義該 job 在被 release 回 queue 後, 至少須等待 60 秒才可在被 worker pick up 執行
Laravel 8 又叫做 backoff
# Conditionally Queueing Listeners
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderPlaced;
use Illuminate\Contracts\Queue\ShouldQueue;
class RewardGiftCard implements ShouldQueue
{
public function handle(OrderPlaced $event)
{
//
}
public function shouldQueue(OrderPlaced $event)
{
return $event->order->subtotal >= 5000;
}
} - Answer:
當 Order model 的 subtotal attribute 大於等於 5000 時, queue 該 listener
# Manually Accessing The Queue
Laravel Events & Listeners 中, 如果我想要在程式碼中可以手動的 release 或 delete 該 listener job, 那我可以在該 Listener 中使用哪一個 trait?
InteractsWithQueue trait
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
public function handle(OrderShipped $event)
{
if (true) {
$this->release(30);
}
}
} - Answer:
若要在 listener job 中可對 job 做 release 或 delete 操作, 需use InteractsWithQueue
# Handling Failed Jobs
Laravel Event & Listener 中, 如果我想要在 Listener 失敗後做相對應的邏輯, 那我可以在 Listener 當中定義哪一個 method?
failed method
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
public function handle(OrderShipped $event)
{
//
}
public function failed(OrderShipped $event, $exception)
{
//
}
} - Answer:
在 listener class 內定義 failed(), 當 listener job failed 時, 執行 failed() 內的邏輯
# Dispatching Events
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Http\Controllers;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
use App\Order;
class OrderController extends Controller
{
public function ship($orderId)
{
$order = Order::findOrFail($orderId);
// Order shipment logic...
event(new OrderShipped($order));
}
} - Answer:
觸發 OrderShipped event
# Event Subscribers
# Writing Event Subscribers
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Listeners;
class UserEventSubscriber
{
public function handleUserLogin($event) {}
public function handleUserLogout($event) {}
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
'App\Listeners\UserEventSubscriber@handleUserLogin'
);
$events->listen(
'Illuminate\Auth\Events\Logout',
'App\Listeners\UserEventSubscriber@handleUserLogout'
);
}
} - Answer:
在 EventSubscriber 的 subscribe method 中定義 event 以及 listener, 然後直接在此 class 中定義 listener 邏輯
# Registering Event Subscribers
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
//
];
protected $subscribe = [
'App\Listeners\UserEventSubscriber',
];
} - Answer:
使用 EventServiceProvider 的 $subscribe property 來註冊事先已建立的 UserEventSubscriber’, EventSubscriber 可以在一個 class 中定義多個 listener 邏輯, 並 map 與之相對應的 event, 這樣就不需要建立多個 class, 每個 class 只定義一個 listener
留言