Webアプリケーションではメール送信処理などは処理が重くなりがちです。
メール送信処理が完了してからレスポンス返すような処理の流れにしていると待機時間が長くなりユーザーがストレスを感じるようなプロダクトになってしまいます。
そういった動作が重い処理はキューを活用するなどして、非同期に処理を実行することでレスポンスが早くなり、ユーザーへのストレスを軽減することができます。
この記事ではLaravelでキューを使ってメール送信処理を実装することで、キューの使い方を解説していきたいと思います。
キューを使うための準備
まずはキューでデータベースを使うための準備をしていきます。
.envファイルの修正
.envファイルのキュー接続設定の項目であるQUEUE_CONNECTIONをdatabaseに変更します。
デフォルトでは同期という意味を持つsyncが設定されています。
databaseに変更することで、キューでデータベースを利用することができるようになります。
QUEUE_CONNECTION=database
キュー用のテーブルを作成
次にキュー専用のテーブルを作成するためのマイグレーションファイルを生成していきます。
下記のコマンドでキューテーブルなどで必要なカラムを定義されているマイグレーションファイルを簡単に生成することができます。
$ php artisan queue:table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('jobs');
}
}
キュー専用のマイグレーションファイルの生成ができたら、マイグレーションを実行しテーブルを作成します。
$ php artisan migrate
これでキューでデータベースを使用するための準備は完了です。
ジョブを実装する
キューを使用するための準備ができたら、早速ジョブを実装していきましょう。
この記事ではメール送信処理を行うジョブを実装していきたいと思います。
ジョブファイルの生成
下記のコマンドでジョブのファイルを生成しましょう。
$ php artisan make:job SendMailJob
生成した直後のSendMailJobファイルは下記のような状態になっています。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendMailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}
ジョブで実行したい処理はhandleメソッド内に処理を記述していきます。
ジョブに処理を実装する
handleメソッド内にメール送信の処理を書いていきましょう。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Mail;
use App\Mail\TestMail;
class SendMailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $name;
private $email;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(string $name, string $email)
{
$this->name = $name;
$this->email = $email;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
// メール送信
Mail::send(new TestMail($this->name, $this->email));
}
}
この記事ではメール送信処理の詳しい内容については割愛していきます。
下記の記事でメール送信処理について詳しく解説しているので、ぜひ参考にしてください。
コントローラーでジョブをキューに登録する
メール送信処理を実装したジョブをコントローラーからキューに登録してあげるように記述していきます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Jobs\SendMailJob;
class MailController extends Controller
{
public function send(Request $request)
{
$name = 'テスト ユーザー';
$email = 'test@example.com';
SendMailJob::dispatch($name, $email);
return redirect('/');
}
}
dispatchメソッドを実行することで、SendMailJobがキューのテーブルに登録されます。
キューのジョブを実行する
キューにジョブを登録することに成功しましたが、このままではジョブのメール送信処理が実行されていないままです。
キューに溜まったジョブは下記のコマンドで実行することができます。
$ php artisan queue:work
キューワーカがキューを監視した状態となり、キューにジョブが溜まっている場合にはそのジョブを実行していきます。
下記のように表示されていればSendMailJobが実行されています。
[2022-03-15 14:25:36][1] Processing: App\Jobs\SendMailJob
[2022-03-15 14:25:36][1] Processed: App\Jobs\SendMailJob
MailHogでも確認すると確かにメールが送信されていることが確認できますね。
まとめ
メール送信機能の実装を通して、キューとジョブの使い方を解説してきました。
キューを用いることで非同期的に処理を実行できるようになり、並列処理が行えます。
少し難易度が高いように感じますが、とてもシンプルな使い方であることがこの記事で分かったことかと思います。
この記事を参考にして、ぜひキューとジョブを使いこなせるようになっていきましょう。