24
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravelでキューってみる

Last updated at Posted at 2019-01-30

Laravelでキューを使ってみます。

キューです。FIFO。先入れ先出し。バックグラウンドで重たい処理をやらせたいときなどに便利なやつです。Laravelでも当然用意されています。今回そのキューでメール送信機能を実装しようと思います。Laravelのバージョンは5.7を使います。Laravelのキューのドライバーとしては、データベース、Redis、Amazon SQSなどがあるのですが、今回はデータベースのキューを使ってみようと思います。

まずLaravelのプロジェクト作成です。

$ composer create-project --prefer-dist laravel/laravel queue-sample

Valetでアクセスしてみます。

スクリーンショット 2019-01-29 18.13.40.png

ユーザ登録機能を作って、登録されたらキューを使って登録完了メールを送ってみます。
マイグレーションの前にデータベースを用意して、接続情報を.envに記述しておきましょう。

$ php artisan make:auth
$ php artisan migrate

スクリーンショット 2019-01-29 18.25.06.png

画面右上に2つリンクが表示されるようになりました。
今回使うのは登録画面のほうです。

スクリーンショット 2019-01-29 18.26.28.png

この画面からユーザ登録出来ます。
登録はapp/Http/Controllers/Auth/RegisterController.php内のcreate()が呼ばれます。
ここでreturnさせる前にメール送信キューにエンキューすればいいのではと思うわけです。

app/Http/Controllers/Auth/RegisterController.php
    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }

その前にメール送信処理のクラスも作ります。

$ php artisan make:mail UserRegistered --markdown=emails.user.registered
app/Mail/UserRegistered.php
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

use App\User;

class UserRegistered extends Mailable
{
    use Queueable, SerializesModels;

    protected $user;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->markdown('emails.user.registered')
            ->subject('ご登録ありがとうございました')
            ->with(['user' => $this->user]);
    }
}
resources/views/emails/user/registered.blade.php
@component('mail::message')
{{ $user->name }} 様

ご登録ありがとうございました。

{{ config('app.name') }}
@endcomponent

これで準備が整いました。
さあここからがキューです。

https://laravel.com/docs/5.7/queues
https://readouble.com/laravel/5.7/ja/queues.html

config/queue.phpでキューの設定をします。
ですが今回はまだデフォルトのままで、.envでキューのドライバーをデータベースに変更します。

.env
QUEUE_CONNECTION=database

次にキュー用のテーブルを作ります。Artisanコマンドが用意されているので便利です。
ひとつはキューのジョブテーブルで、もうひとつは実行が失敗したジョブのテーブルです。

$ php artisan queue:table
$ php artisan queue:failed-table
$ php artisan migrate

キューで何を処理するかを記述するジョブクラスを作ります。

$ php artisan make:job SendRegisteredMail

作られたジョブクラスはapp/Jobs以下に配置されます。
SendRegisteredMail.phpにはコンストラクタとhandle()メソッドが用意されています。
コンストラクタでジョブに必要なデータを渡し、handle()で実際にやりたい処理を行うという流れです。

app/Jobs/SendRegisteredMail.php
<?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 App\User;
use App\Mail\UserRegistered;
use Illuminate\Support\Facades\Mail;

class SendRegisteredMail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $user;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(User $user)
    {
        $this->user = $user;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Mail::to($this->user->email)->send(new UserRegistered($this->user));
    }
}

そして、ユーザ登録部分にキューを発行する処理を追加します。
ジョブクラスのdispatch()を実行します。

app/Http/Controllers/Auth/RegisterController.php
<?php

namespace App\Http\Controllers\Auth;

use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

use App\Jobs\SendRegisteredMail;

class RegisterController extends Controller
{

    〜〜〜〜〜

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        $user = User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);

        SendRegisteredMail::dispatch($user);

        return $user;
    }
}

さて、これでユーザ登録するとメール送信のキューが発行されます。
しかしこのままだとキューを取り出して処理がされません。
キューワーカでのキューの監視が必要となってきます。
そこでArtisanコマンドでキューワーカを起動します。

$ php artisan queue:work

これでキューが監視され処理されます。ユーザ登録するとメールが送信されたことが確認出来ると思います。
キューワーカのコンソールでも以下のように出力されます。
失敗すると設定した回数分リトライされます。

$ php artisan queue:work
[2019-01-30 02:00:00][2] Processing: App\Jobs\SendRegisteredMail
[2019-01-30 02:00:00][2] Processed:  App\Jobs\SendRegisteredMail

公式ドキュメントでも述べられているとおり、キューワーカを永続的に実行するためにはSupervisorのようなプロセスモニタが必要です。

という感じで、キューという仕組みとしてはわかりやすいけれど実装するとしたら難しい機構をLaravelでは手軽に使用出来ることがお分かりいただけたと思います。
公式ドキュメントによるともっと詳細に設定出来るので調べてみるとよいと思います。それでは!

追記

そもそもLaravelのメール送信機能もキューを使ってるっぽいので冗長になっているのでは……

24
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?