たとえばメールの一斉送信機能の実装で、「送信ボタンを押してから、遷移先ページの読み込み完了までに時間がかかる……」というケースがあります。ページが開くまで、メール送信処理に時間がかかっているためです。
このケースを解決するには、ページ遷移の方を優先して、裏側(非同期)でメール送信処理を実行してもらいます。
このバックグラウンド処理をLaravelで実現してくれるのが「キュー」です。
キューを使用することで、処理を非同期で実行でき、処理の遅延やサーバーの負荷を軽減できます。
目次
キューのイメージ
Laravelのキューを利用して、メールの一括送信を実装する場合の、おおまかなイメージは以下のとおりです。
- (フロント)「メール一括送信」などをクリック
- キュー(jobsテーブル)にジョブが保存
- (フロント)ページ遷移またはリダイレクト
- バックグラウンドでジョブをひとつずつ処理
Laravelでメール一括送信用のキューとジョブを実装する手順
基本的な方法は、公式ドキュメントに沿って進めています。
1. ジョブを保持するためのテーブルを作成
まずはマイグレーションファイルを作成し、そのままマイグレーションを実行します。
php artisan queue:table
php artisan migrateこれで、データベースにjobsというテーブルが作成されます。
2. .envファイル内のQUEUE_CONNECTION変数を設定
.envファイルのQUEUE_CONNECTIONをdatabaseにします。
QUEUE_CONNECTION=database3. ジョブクラスの作成
以下のようなコマンドを打つことで、app/Jobsディレクトリにジョブファイルを作成できます。ジョブ名は任意に決めてください。
php artisan make:job SendNotificationEmail4. メール送信処理をジョブに記載
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設定」を参考にしてください。

