たとえばメールの一斉送信機能の実装で、「送信ボタンを押してから、遷移先ページの読み込み完了までに時間がかかる……」というケースがあります。ページが開くまで、メール送信処理に時間がかかっているためです。
このケースを解決するには、ページ遷移の方を優先して、裏側(非同期)でメール送信処理を実行してもらいます。
このバックグラウンド処理をLaravelで実現してくれるのが「キュー」です。
キューを使用することで、処理を非同期で実行でき、処理の遅延やサーバーの負荷を軽減できます。
目次
キューのイメージ
Laravelのキューを利用して、メールの一括送信を実装する場合の、おおまかなイメージは以下のとおりです。
- (フロント)「メール一括送信」などをクリック
- キュー(jobsテーブル)にジョブが保存
- (フロント)ページ遷移またはリダイレクト
- バックグラウンドでジョブをひとつずつ処理
Laravelでメール一括送信用のキューとジョブを実装する手順
基本的な方法は、公式ドキュメントに沿って進めています。
1. ジョブを保持するためのテーブルを作成
まずはマイグレーションファイルを作成し、そのままマイグレーションを実行します。
php artisan queue:table
php artisan migrate
これで、データベースにjobs
というテーブルが作成されます。
2. .envファイル内のQUEUE_CONNECTION変数を設定
.envファイルのQUEUE_CONNECTION
をdatabase
にします。
QUEUE_CONNECTION=database
3. ジョブクラスの作成
以下のようなコマンドを打つことで、app/Jobsディレクトリにジョブファイルを作成できます。ジョブ名は任意に決めてください。
php artisan make:job SendNotificationEmail
4. メール送信処理をジョブに記載
handleメソッドに、Mailableクラスなどで作ったメール送信処理を書きます。このhandle
メソッドは、キューによってジョブが処理されるときに呼び出されます。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use App\Mail\InformationNotification;
class SendNotificationEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $address;
protected $information_text;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($address, $information_text)
{
$this->address = $address;
$this->information_text = $information_text;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// メールの送信処理
Mail::to($this->address)->send(new InformationNotification($this->information_text));
}
}
コンストラクタの定義や、プロパティの定義、useでのMailableクラスのインポートも忘れず書き加えましょう。
4. メール送信を実行する場所をジョブのdispatchメソッドに置き換える
コントローラーなどで本来メール送信処理を実行していた箇所を、ジョブのdispatchメソッドに置き換えます。
use App\Jobs\SendNotificationEmail;
class TestController extends Controller
{
public function update(Request $request) {
// 省略
$information_text = "お知らせです。";
foreach ($users as $user) {
dispatch(new SendNotificationEmail($user, $information_text));
}
// 省略
}
}
このdispatchが実行されると、先ほど作成したjobsテーブル(キュー)にジョブが蓄積されていきます。
実際に、この段階で処理を実行すると、以下のようにjobsテーブルに入ります。
しかし、まだメールは送信されていません。このジョブレコードをバックグラウンドでひとつひとつ実行していくイメージになります。
5. キューのジョブを処理してメール送信する
キューに投入されたジョブを処理して、実際にメールを送信するには、以下のコマンドでキューワーカを実行する必要があります。
php artisan queue:work
うまくいくと、以下のようにProcessed
となるはずです。
逆にうまくいかない場合は、Failed
となります。この場合はログなどを見て修正しましょう。
メールが届いているかも確認してみましょう。ちなみに、メールのテスト送信には、「Mailtrap」というサービスがおすすめです。無料でテスト用の受信トレイを利用できます。
関連記事 Mailtrapの使い方(Laravelでの使い方を解説しています)
Mailtrapを使うと、以下のように一斉送信メールが届いているのを確認できました。
ジョブを永続的にバックグランド実行するには
なお、本番環境などでキューワーカ(queue:work
)をバックグラウンドで永続的に実行(監視)し続けるには、モニタリングツールが必要になります。queue:work
はさまざまな原因で停止する可能性があるためです。
LaravelではモニタリンツールとしてSupervisorが推奨されています。詳しくは、「Supervisor設定」を参考にしてください。