Queue(キュー)の機能を利用すると、ある任意の処理をジョブ( job)として保存・記録して、それら一連のジョブを非同期処理として実行することができます。
ジョブを保存するキュードライバとしての選択肢は、MySQL等のデータベース、Redis、Amazon SQSなどがあります(本記事ではMySQLを利用)。ジョブをキューへと送ることをディスパッチ(dispatchというメソッド)と呼び、コントローラーの適当な箇所に設定します。
キューに記録されたジョブ(より正確に言えば、ジョブのスタック(stack)としての塊がキュー)は、キューワーカによって実行されます。
※本記事は下記関連ページの続きです。実装した「メールの送信機能」をジョブ(クラス)として作成し直し、Queueの機能を利用して非同期処理を実装してみます。
関連ページ
おおまかに以下のような手順で構築します。
・ジョブを記録するキュードライバとしてデータベース(テーブル)を用意する
・非同期処理を記述するジョブクラスの作成・コントローラーにジョブをディスパッチする処理を記述
・キューワーカでジョブの実行
jobsテーブルの準備
.envファイルのQUEUE_CONNECTIONをsyncからdatabaseに変更します。
1 |
QUEUE_CONNECTION=database |
ジョブを保存するためのjobsテーブルのマイグレーションファイルを作成します。
1 |
$ php artisan queue:table |
マイグレーションを実行します。
1 |
$ php artisan migrate |
以下のようなjobsテーブルが生成されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mysql> SHOW COLUMNS FROM jobs; +--------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+---------------------+------+-----+---------+----------------+ | id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | | queue | varchar(255) | NO | MUL | NULL | | | payload | longtext | NO | | NULL | | | attempts | tinyint(3) unsigned | NO | | NULL | | | reserved_at | int(10) unsigned | YES | | NULL | | | available_at | int(10) unsigned | NO | | NULL | | | created_at | int(10) unsigned | NO | | NULL | | +--------------+---------------------+------+-----+---------+----------------+ 7 rows in set (0.01 sec) |
ジョブクラスの作成
SendHelloEmailという名前のジョブクラスを作成します。このジョブクラス内に非同期処理を記述します。
下記コマンドによって、JobsディレクトリとSendHelloEmail.phpファイルが生成されます。
1 |
$ php artisan make:job SendHelloEmail |
下記のように編集します。
app/Jobs/SendHelloEmail.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?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; use App\Mail\HelloEmail; use Mail; class SendHelloEmail implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $data; /** * Create a new job instance. * * @return void */ public function __construct($data) { $this->data = $data; } /** * Execute the job. * * @return void */ public function handle() { Mail::to('admin@hoge.co.jp')->send(new HelloEmail($this->data)); } } |
34〜37行目
handle()には非同期として実行されるジョブとしての処理を記述します。ここでは、上述の関連ページおいて元々コントローラ(ContactController.php)側に記述していたMailファザードによるメール送信を記述しています。
次にコントローラに、ジョブをディスパッチする処理を記述します。
app/Http/Controllers/ContactController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use App\Jobs\SendHelloEmail; class ContactController extends Controller { public function index() { return view('contact.index'); } public function send(Request $request) { $rules = [ 'name' => 'required|max:10', 'email' => 'required|email', 'message' => 'required|max:1000', ]; $messages = [ 'name.required' => '名前を入力して下さい。', 'name.max' => '名前は10文字以下で入力して下さい。', 'email.required' => 'メールアドレスを入力して下さい。', 'email.email' => '正しいメールアドレスを入力して下さい。', 'message.required' => 'メッセージを入力して下さい。', 'message.max' => 'メッセージは1000文字以下で入力して下さい。', ]; $validator = Validator::make($request->all(), $rules, $messages); if ($validator->fails()) { return redirect('/contact') ->withErrors($validator) ->withInput(); } $data = $validator->validate(); SendHelloEmail::dispatch($data); session()->flash('success', '送信いたしました!'); return back(); } } |
45行目
ジョブクラスのdispatchメソッドを記述しています。このタイミングでジョブがキューへと記録されます(jobsテーブルに記録される)。引数の$dataはジョブクラスのコンストラクタへと渡されます。
最後にキューワーカを起動します。このワーカによってキューに記録されたジョブが実行されていきます。
1 |
$ php artisan queue:work |
※ジョブクラスを編集した場合はこのキューワーカを再起動して下さい。
仮にdispatchに下記のようなdelayの処理を施すと、キュー(jobsテーブル)に投入されたジョブは1分後に実行されるようになります。
1 |
SendHelloEmail::dispatch($data)->delay(now()->addMinutes(1)); |
dispatchされたタイミングでjobsテーブルにはジョブが記録されますが、1分後にワーカによって実行されたタイミングでその記録が削除されるのが確認できます。
参照ページ