
Laravel の Events/Listeners(イベント/リスナ)を使用して非同期処理を実装していきます
具体的には、Events 発行後 Listeners で検知し、Listeners の処理を Queue に投入して非同期で処理を実行させます。
Laravel の Events/Listeners で非同期処理を実装する方法
Events/Listeners の作成と登録を行う
Events/Listeners(イベント/リスナ)の作成と登録をしていきます。
app/Providers/EventServiceProvider.php
/**
* The event listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
"App\Events\SampleEvent" => [
"App\Listeners\SampleListener"
]
];
$listen というメンバ変数に、「キー:SampleEvent、値:SampleListener」を設定。その後、下記コマンドを実行することで、定義したファイルが生成されます。
php artisan event:generate
app/Events/SampleEvent.php
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class SampleEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
app/Listeners/SampleListener.php
<?php
namespace App\Listeners;
use App\Events\SampleEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SampleListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param \App\Events\SampleEvent $event
* @return void
*/
public function handle(SampleEvent $event)
{
//
}
}
make:event
や make:listener
といった Artisan コマンドを利用して、個々に Event と Listener を作成することも可能です。その場合は以下のようなコマンドを実行してあげます。
php artisan make:event SampleEvent
php artisan make:listener SampleListener --event=SampleEvent
Event を発行する
続いて Event(イベント)の発行です。Event の発行に関しては、event 関数を用いれば簡単に Event を発行することができます。
app/Http/Controllers/SampleController.php
<?php
namespace App\Http\Controllers;
use App\Events\SampleEvent;
use Illuminate\Http\Request;
class SampleController extends Controller
{
/**
* Handle the incoming request.
*
* @param string $sample
*/
public function __invoke(string $sample)
{
// $sampleには適当な文字列が入っているとします
event(new SampleEvent($sample));
}
}
Event と Listener に処理を書いていく
SampleController が呼ばれると __invokeメソッド内の event 関数が実行されますが、SampleEvent と SampleListener には何も処理を書いていないので、こちらに処理を書いていきます。
まずは SampleEvent から。
app/Events/SampleEvent.php
<?php
namespace App\Events;
class SampleEvent
{
/**
* Sample
*
* @var string
*/
public $sample;
/**
* Create a new event instance.
*
* @param string $sample
* @return void
*/
public function __construct(string $sample)
{
$this->sample = $sample;
}
/**
* Get Sample
*
* @return string
*/
public function getSample()
{
return $this->sample;
}
}
Event クラスでは、Listener クラスで利用するデータ等の保持を記載しておきます。broadcastOn メソッドは使用しないので削除しました。
app/Listeners/SampleListener.php
<?php
namespace App\Listeners;
use App\Events\SampleEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SampleListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param SampleEvent $event
* @return void
*/
public function handle(SampleEvent $event)
{
// $event->getSample()のようにEvent側の処理を呼ぶことできる
// 何らかの処理を記載
}
}
Listeners に関しては、handle メソッド内に処理を書いていきます。今回は Sample ということで具体的な処理内容については記載していません。
Listener の処理を Queue に投入して非同期で処理を実行させる
現在の状態だと、同期処理で実行されるので、Listener の処理を Queue に投入して非同期で処理を実行させる方法について書いていきます。
Queue の設定を行う
まずは Queue の設定から。今回は Queue ドライバとして DB を利用するので、QUEUE_CONNECTION に database を指定します。
QUEUE_CONNECTION=database
jobs・failed_jobs テーブルの作成を行う
続いて Listener の処理を保存するための jobs テーブルと、失敗した job を格納するための failed_jobs テーブルを作成します。
failed_jobs テーブルに関しては、Laravel をインストールした際に migration ファイルが用意されているかと思うので、そのファイルを使用します。
php artisan queue:table
php artisan migrate
キューワーカも起動させておきましょう。
php artisan queue:listen
キューワーカに関しては、supervisor でプロセス監視をしておくと良いです。
Listener で ShouldQueue インターフェースを継承する
Listener の処理を Queue に投入し、非同期で処理を実行するため、SampleListener クラスに ShouldQueue インターフェースを継承させます。
app/Listeners/SampleListener.php
class SampleListener implements ShouldQueue
また、Listner の処理の送信先となる Queue 名や、処理開始までの実行時間も指定することができます。
app/Listeners/SampleListener.php
<?php
namespace App\Listeners;
use App\Events\SampleEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class SampleListener implements ShouldQueue
{
/**
* 接続名
*
* @var string
*/
public $connection = "database";
/**
* キュー名
*
* @var string
*/
public $queue = "sample";
/**
* 処理開始されるまでの時間(秒)
*
* @var int
*/
public $delay = 20;
}
失敗した Job の処理を行う
Queue に投入した処理が失敗した場合、Listener 上の failed メソッドが呼ばれます。なので、ここに失敗通知を送る処理などを記載しておくと良いでしょう。
app/Listeners/SampleListener.php
/**
* 失敗したJobの処理
*
* @param SampleEvent $event
* @param Exception $exception
*/
public function failed(SampleEvent $event, Exception $exception)
{
// 失敗した内容をメール通知する処理などを記載
}
Queue ファサードの before や after、failing メソッドを使用して、キュー投入したジョブが処理される前後や失敗時に実行するコールバックを指定することもできます。
まとめ|Laravel の Events/Listeners で非同期処理を実装する方法
ここまで、「Laravel の Events/Listeners で非同期処理を実装する方法」について書いてきました。
流れとしては、Events 発行後 Listeners で検知して、Listeners の処理を Queue に投入して非同期で処理を実行させるというもの。

Listeners の処理を Queue に投入して処理を実行させる部分に関しては、あまり情報が落ちていなかったので実装するのに一苦労しました
コメント