【Laravel】非同期処理

もくじ

環境

$ php artisan --version
Laravel Framework 7.6.2
$ mysql --version
mysql  Ver 8.0.22
$ php -v
PHP 7.2.33

テーブル作成

「非同期で実行する処理を格納するテーブル」を作成するマイグレーションファイルを作成します。

$ php artisan queue:table
Migration created successfully!

この時、失敗した場合の処理を格納するテーブルも同時に作成します。これはあってもなくてもいいです。

$ php artisan queue:failed-table
Migration created successfully!

マイグレートしてテーブル作成します。

$ php artisan migrate
Migrating: 2020_12_16_062249_create_jobs_table
Migrated:  2020_12_16_062249_create_jobs_table (0.52 seconds)
Migrating: 2020_12_16_062319_create_failed_jobs_table
Migrated:  2020_12_16_062319_create_failed_jobs_table (0.04 seconds)

上記を実行すると、マイグレートしていないファイルが一斉に実行されます。

GUIなど使って、テーブルが作成されているか確認しましょう。

.envファイルの更新

.envを開いてキューサービスをdatabaseへ切り替えます。

Laravelのバージョンを確認した上で下記の通り更新しましょう。

// Laravel 5.7〜
QUEUE_CONNECTION=database

// Laravel 〜5.6
QUEUE_DRIVER=database

余談ですが、Laravelには”sync”, “database”, “beanstalkd”, “sqs”, “redis”などのキューが準備されており、デフォルトではsyncになっています。その中でも最も設定が簡単なのがdatabaseキューだそうです。

Jobファイルを作成

$ php artisan make:job SampleJob
Job created successfully.

SampleJobの箇所はファイル名になります。非同期処理の中身に応じてファイル名を設定するといいでしょう。

メール送信のJobならSendMailなど。

このファイルは/app/Jobs/配下に作成されます。

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 SampleJob 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()
    {
        return "非同期処理実行";  // 追記
    }
}

特に指定しなければhandleメソッドが初期値として実行されます。

今回はわかりやすく"非同期処理実行"をいうテキストを返す処理を追記してみました。

非同期処理を実装

コントローラーに先ほど作った非同期処理のJobを用いて実装します。

キューを使ってジョブを実行する場合はdispatchメソッドを使用します。dispatchメソッドを実行することでジョブはキューに送られます。

use App\Jobs\SampleJob;

class IndexController extends Controller
{
  public function job(){
    SampleJob::dispatch();

    echo ('非同期処理実行後のテキスト');
  }
}

今回はSampleJobの中身はテキストを返すだけなので非常に軽いですが、これがメールを大量送信したりDBのレコードを大量に出力したりする処理だと大きな時間を要する場合があります。

しかし、このように非同期処理を実装することでSampleJob::dispatch();を実行してから次にechoされるのではなく、SampleJob::dispatch();を呼び出すとすぐにechoされます。

順番に実行するのではなくあくまで非同期なのです。

非同期処理の登録

ではこのメソッドを実行してみます。

するとjobsテーブルにjobが登録されます。

f:id:bonoponz:20201216160343p:plain

これは非同期処理のJobをjobsテーブルに登録しただけであり、まだ実行されていません。

Jobの起動(非同期処理の実行)

サーバで下記を実行します。

$ php artisan queue:work
[2020-12-16 07:07:49][1] Processing: App\Jobs\SampleJob
[2020-12-16 07:07:55][1] Processed:  App\Jobs\SampleJob

jobsテーブルに登録された処理を実行してくれます。queue:workを終了するまで常に実行しています。そのため、Jobクラスを編集した場合はこのqueue:workを再起動ctrl + Cして再実行)して下さい。

実行が成功するとこのレコードは削除され、失敗するとfailed_jobsテーブルに登録されます。

確認すると先ほど登録されたはずのレコードがjobsテーブルから削除されています。

f:id:bonoponz:20201216161550p:plain

これで非同期処理の実装完了です!

参考URL

キュー 7.x Laravel

Laravel JobとQueueも設定はこんなに簡単 | アールエフェクト

【Laravel】非同期処理の使用方法! 俺用メモ

Laravelのデータベースキュー投入とジョブ処理で非同期処理を実現する~劇的に高速化できるユーザーレスポンス~

Laravel Queueを利用して非同期によるメール送信