概要
Laravel5.5でイベントを用いた実装をするにあたり、調査した内容を共有致します。
イベントの概要については公式Docを参照して頂ければと思います。
基本的に登場人物は以下の4つになります。
①イベント
②イベントリスナー
③上記2つを紐づけるサービスプロバイダー
④イベントを発火するクラス
利用方法
①App\Providers\EventServiceProviderにイベントとイベントリスナーを$listenに定義します。
例として"TestEvent"というイベントに対して"TestListener1"と"TestListner2"の二つのリスナーを定義します。
protected $listen = [
'App\Events\TestEvent' => [
'App\Listeners\TestListner1',
'App\Listeners\TestListner2',
],
];
②artisanコマンドで上記で定義したリスナーを作成します。
これでイベントファイル1つとイベントリスナーファイル2つが自動作成されたはずです。
php artisan event:generate
③これでコントローラなどからイベントを発火できます。
イベントが発火されるとそのイベントに紐づいたリスナーのhandleメソッドが呼ばれます。
リスナーのhandleメソッドでreturnした値はeventヘルパの返り値として取得できます。
$response = event(new TestEvent());
調査事項① イベントにパラメタを渡し、リスナーから値を返却できるか
【結論】下記の要領で出来る。
①コントローラで、イベントを発火するときにパラメタを渡す
$response = event(new TestEvent("test parameter"));
②イベントで、コンストラクタとpublicなプロパティを設定する
class TestEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $parameter;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($parameter)
{
$this->parameter= $parameter;
}
}
③リスナーで、イベントのプロパティにアクセスする
class TestListener1
{
public function handle(TestEvent $event)
{
return $event->parameter; //これでイベントのプロパティにアクセス可能
}
}
④これでeventヘルパの返却値に配列で値が返ってきます。
array:1 [▼
0 => "test parameter"
]
調査事項② 複数リスナー時の実行順番と返却値がどうなるか
【結論】複数リスナーの実行をするとき、キューを使用しない場合、EventServiceProviderに設定した順番通りに"同期実行"される
protected $listen = [
'App\Events\TestEvent' => [
'App\Listeners\TestListner1', // 先に実行される、 return "listen 1"を記述してある
'App\Listeners\TestListner2', // 後に実行される、 return "listen 2"を記述してある
],
];
この状態でイベントを発火する
$response = event(new TestEvent());
$responseの中身は下記のようになる。
array:2 [▼
0 => "listen 1"
1 => "listen 2"
]
同期処理のため、TestListner1の処理をsleep等で遅らせてもこの順番で返却された。
調査事項③ トランザクション制御できるか
【結論】できる
試したこと
①リスナーで適当なテーブルにInsertする処理を記述
public function handle(TestEventInaba $event)
{
$account = new Account;
$account->id = 999;
$account->is_available = 1;
$account->login_id = "user9999";
$account->name = "SampleName";
$account->password = "SamplePass";
$account->save();
}
②コントローラ側でイベント発火時にトランザクション制御を記述して実験
DB::beginTransaction();
$response = event(new TestEvent());
DB::rollback(); //またはDB::commit();
③コミットもロールバックも正常に動作することを確認