【Laravel】イベントとリスナの使い方
はじめに
Laravelではイベントとリスナを使って、特定の事象が発生した時に実行される処理を定義することができます。
これはデザインパターンの一種で「Observer(観察者)パターン)」といいます。
イベントが観察される側で、リスナが観察する側です。
つまり、イベントが発行されるとリスナで定義しておいた処理が実行されるという流れです。
今回はユーザー登録を例に実装していき、イベント、リスナ、Observerパターンについて理解していただければと思います。
環境
- Laravel 9.38.0
- PHP 8.1.12
Laravel Sailで環境構築しています。
https://readouble.com/laravel/9.x/ja/sail.html
参考
今回の実装について
ユーザーが新規登録を行なった場合に以下の2つの処理を実装します。
- ウェルカムメールを送信する
- メルマガ登録を行う
これらをイベントを使う場合と使わない場合を比較して、利点についても理解していただければと思います。
イベントを使う利点とは
以下が挙げられます。
①コントローラーへの記述を減らすことでのメンテナンス性向上
→全ての処理をコントローラーで行うこともできますが、イベントとリスナを使うことで処理を分離させることができ、メンテナンス姓が向上します。
②変更容易性の向上
→管理者に新規ユーザーの情報を通知する新機能を追加することになった場合も、処理を別のクラスに分けているためコントローラーの記述を変更する必要が無く、他の箇所への影響範囲が最小で済みます。
③テスト容易性の向上
→各クラスを個別にテストすることができるため、テストもしやすくなります。
イベントを使用しない場合
まず、イベントを使用しない場合を実装していきます。
UserController
を作成し、以下のようにregsiter
メソッドを作成します。
// 中略
use App\Mail\WelcomeMail;
use App\Models\MailingList;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
// 中略
public function register(Request $request)
{
User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
Mail::to($request->email)->send(new WelcomeMail());
MailingList::create([
'email' => $request->email
]);
return response()->json(['result' => 'success']);
}
ユーザー登録後に、メール送信処理とメルマガ登録処理を行なっています。
イベントを使用する場合
次にイベントを使用する場合で実装していきます。
流れは以下の通りです。
①イベントとリスナをサービスプロバイダーに登録
②イベントとリスナの生成
③イベントの定義
④リスナの定義
⑤コントローラーでイベントを発行する
①イベントとリスナをサービスプロバイダーに登録
事前にEventServiceProvider
へイベントとリスナを登録しておくことで、一括でファイルを作成することができます。
EventServiceProvider
のlisten
プロパティに以下のようにイベントとリスナを登録します。
// 中略
use App\Events\UserRegistered;
use App\Listeners\SendWelcomeMail;
use App\Listeners\SubscribeToMailingList;
// 中略
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
UserRegistered::class => [
SendWelcomeMail::class,
SubscribeToMailingList::class
]
];
}
②イベントとリスナの生成
以下のコマンドを入力することで、先ほど登録したUserRegistered
イベント、SendWelcomeMail
リスナ、SubscribeToMailingList
リスナを生成します。
$ sail artisan event:generate
③イベントの定義
app/Events
配下にUserRegistered.php
が生成されているので、以下のように更新します。
// 中略
use App\Models\User;
// 中略
class UserRegistered
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* ユーザーインスタンス
*
* @var App\Models\User;
*/
public $user;
/**
* イベントインスタンスの生成
*
* @param User $user
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}
上記のようにUserRegisterd
イベントはUser
インスタンスを持つだけで、ロジックはありません。
④リスナの定義
リスナのファイルはapp/Listeners
配下に生成されます。
まずは、SendWelcomeMail
リスナのhandle
メソッドにウェルカムメール送信処理を記述します。
// 中略
use App\Events\UserRegistered;
use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Mail;
class SendWelcomeMail
{
// 中略
/**
* ウェルカムメール送信処理
*
* @param \App\Events\UserRegistered $event
* @return void
*/
public function handle(UserRegistered $event)
{
Mail::to($event->user->email)->send(new WelcomeMail());
}
handle
メソッドでUserRegistered
インスタンスを受け取り、そのインスタンスが持つUser
のメールアドレスに対してウェルカムメールを送信します。
次にSubscribeToMailingList
のhandle
メソッドにメルマガ登録処理を記述します。
// 中略
use App\Events\UserRegistered;
use App\Models\MailingList;
class SubscribeToMailingList
{
// 中略
/**
* メルマガ登録処理
*
* @param \App\Events\UserRegistered $event
* @return void
*/
public function handle(UserRegistered $event)
{
MailingList::create([
'email' => $event->user->email
]);
}
}
同じくhandle
メソッドでUserRegistered
インスタンスを受け取り、そのインスタンスが持つUser
のメールアドレスを登録します。
⑤コントローラー
最後にコントローラーでイベントを発行します。
ユーザー登録後に、event
ヘルパー関数を使ってUserRegistered
イベントを発行します。
// 中略
use App\Events\UserRegistered;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
/**
* ユーザー新規登録
*
* @param Request $request
* @return JsonResponse
*/
public function register(Request $request): JsonResponse
{
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new UserRegistered($user));
return response()->json(['result' => 'success']);
}
}
これでユーザー登録時にUserRegistered
イベントが発行されウェルカムメール送信とメルマガ登録がされるようになったかと思います。
さいごに
今回はユーザー登録を例にLaravelのイベントとリスナを使ってみました。
少しでもお役に立てれば嬉しいです。
最後までお読みいただきありがとうございました。
Discussion