# 前言
學習一個框架, 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
留言