LoginSignup
40
44

More than 5 years have passed since last update.

メールはキューを使って送信しよう!(Laravel/Lumen使ってたらね)

Last updated at Posted at 2015-07-11

「サンクスメールを送信するとかの処理は即時じゃなくてもいいから、サイトのレスポンスはとにかく速く」という雰囲気になった時はLaravel/Lumenのキューを使う機会が来たということじゃないでしょうか。
というわけで、ちょっとやってみました。

前提

  • サンプルコードはLumen5.1です(Laravel5.1~5.3でも確認済です)
  • キュードライバは、データベースドライバを使います。
  • 設定はこの記事の下の方にある「補足」の通りです。

Laravel/Lumenのキューに対する自分の中の理解

ジョブクラスのインスタンスをjobsテーブルに登録すると、Laravel/Lumenがジョブをキューとして実行していってくれる。

やる事

  1. jobsテーブルを作成する
  2. ジョブクラスを作成する
  3. キューリスナーを実行する

1.jobsテーブルを作成する

これはドキュメントにある通り、マイグレーションファイルを生成して、マイグレーションを実行します。

php artisan queue:table
php artisan migrate

2.ジョブクラスを作成する

これもドキュメントにある通りですが、以下のようにプロパティを使う場合は必ず指定しとかないと、キューの実行時に例外を投げよります。

app/Jobs/SendEmail.php
<?php

namespace App\Jobs;

use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendEmail extends Job implements SelfHandling, ShouldQueue {

    /** @var string view name */
    protected $view;
    /** @var array ビューに割り当てるデータ */
    protected $data;
    /** @var array メールの送信先等の属性 */
    protected $mail;

    public function __construct($view, $data, $mail)
    {
        $this->view = $view;
        $this->data = $data;
        $this->mail = $mail;
    }

    /**
     * @param Mailer $mailer
     */
    public function handle(Mailer $mailer)
    {
        $mail = $this->mail;
        $mailer->send($this->view, $this->data, function ($message) use ($mail)
        {
            $message->subject($mail['subject'])
                    ->from($mail['from'], $mail['f_name'])
                    ->to($mail['to'], $mail['to_name']);
        });
    }

}

Laravel5.3ではクラスの継承などが以下のように変更されています。

app/Jobs/SendEmail.php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendEmail implements ShouldQueue {

    use InteractsWithQueue, Queueable, SerializesModels;

    /** @var string view name */
    protected $view;
    /** @var array ビューに割り当てるデータ */
    protected $data;
    /** @var array メールの送信先等の属性 */
    protected $mail;

    public function __construct($view, $data, $mail)
    {
        $this->view = $view;
        $this->data = $data;
        $this->mail = $mail;
    }

    /**
     * @param Mailer $mailer
     */
    public function handle(Mailer $mailer)
    {
        $mail = $this->mail;
        $mailer->send($this->view, $this->data, function ($message) use ($mail)
        {
            $message->subject($mail['subject'])
                    ->from($mail['from'], $mail['f_name'])
                    ->to($mail['to'], $mail['to_name']);
        });
    }

}

3.キューリスナーを実行する

これもまたドキュメントにある通りです。

php artisan queue:listen

ジョブのインスタンスをjobsテーブルに登録する

今回は、ブラウザ経由でジョブを登録するので、ラウティングとコントローラーを作成します。
メールのテンプレートにビューファイルを使用するのでついでに作成します。
(laravel5.3ではラウティングファイルにroutes/web.phpを使います)

app/Http/routes.php
<?php
// for Lumen 5.1
$app->get('reserve', 'ReserveController@store');
// for Laravel 5.1(LTS) ~ 5.3
Route::get('reserve', 'ReserveController@store');
app/Http/Controllers/ReserveController.php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Jobs\SendEmail;

class ReserveController extends Controller {

    public function store()
    {
        $mail = [
            'from'    => 'nielsen@test.com',
            'f_name'  => 'Nelsen',
            'to'      => 'poulsen@test.com',
            'to_name' => 'Poulsen',
            'subject' => 'Thanks for your reservation.'
        ];
        // ジョブのインスタンスを生成
        $job = new SendEmail(
            'emails.reservation',
            ['name' => ucfirst('niikunihiro')],
            $mail
            );
        // jobs テーブルに登録
        $this->dispatch($job);
        echo 'finished!';
    }

}
resources/views/emails/reservation.blade.php
Hi! {{$name}}.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab dolor eius eos hic magnam minus, nihil odio omnis quae quas velit, veritatis. Assumenda earum porro, quisquam repellendus sed tempora voluptatibus.

ブラウザで確認するので、ビルトインサーバを立ち上げます。

php artisan serve

http://localhost:8000/reserve」にアクセスすると、ログファイルにメールの内容が書込まれているので確認して終わりです。

storage/logs/lumen.log
[2015-07-11 07:14:46] lumen.DEBUG: Message-ID: <84c77b0b510235de0e6a54621294c3ef@swift.generated>
Date: Sat, 11 Jul 2015 07:14:46 +0000
Subject: Thanks for your reservation.
From: Nelsen <nielsen@test.com>
To: Poulsen <poulsen@test.com>
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

Hi! Niikunihiro.

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab dolor eius eos hic magnam minus, nihil odio omnis quae quas velit, veritatis. Assumenda earum porro, quisquam repellendus sed tempora voluptatibus.  

補足

設定ファイル

# APP_KEY に 32 文字の乱数(じゃなくてもいいけど)を設定する
# APP_KEY が正しく設定されてないとエラーになります
APP_KEY=Dwwf1OGD9vriSvpWIZhDubkPKWdnNgSi

# データベースドライバを使用
QUEUE_DRIVER=database

# 送信内容をログで見たいので
MAIL_DRIVER=log

Lumenの場合は、illuminate/mailパッケージを追加する

composer.json
{
    "require": {
        "laravel/lumen-framework": "5.1.*",
        "vlucas/phpdotenv": "~1.0",
        "illuminate/mail": "5.1.*"
    },
}
composer update illuminate/mail
40
44
1

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
40
44