Laravel8 Mailable 本文を動的にセット

最終更新日

Mailable使ったメール送信の場合、必ずbladeテンプレートを使う必要がある。

Mail::to(‘info@hoge.co.jp’)->send(Mailableクラスインスタンス);

別途Mailableを継承したクラスを作成し、

その中でメール本文に該当するbladeテンプレートを指定する。

Mailableを使ったメール送信のサンプルコードはGoogleで検索するとたくさん出てくるのでここでは割愛する。

今回やりたいことはこうだ。

とあるシステムでは、メール本文をデータベースで管理している。

更に本文は、Smartyテンプレート形式を採用しており、

送信前に、必要な変数には該当するテーブルの該当するカラムの値に置き換えて送信される。

こういう仕様のシステムの一部をLaravelに置き換える必要があり色々と試した。

  • bladeじゃなくsmartyを使ってメール本文を構築できるか
  • Mailableを使わないでメール送信してみるか

結果、うまくいかずbladeを使ってやってみるが、

データベース上に無数にあるメール本文データを全てbladeファイルに変換するのは効率が悪すぎるし

いつどこで誰が本文を変えるかわからない。

相当な時間を費やし、発想からものすごく簡単な方法で解決した。

email.blade.phpを作成する

resources/views/emails/email.blade.php

{{$context}}

内容はこれだけ。

で、context変数に、Smartyでビルドした本文をセットするだけ

app/Mail/HogeMail.php

namespace App\Mail;
 
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use SmartyBC;
 
class HogeMail extends Mailable
{
    use Queueable, SerializesModels;
    public $data;
 
    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }
 
    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $smarty = new SmartyBC();
        // Smartyテンプレート用の置き換え変数
        $replacement = [
          'hoge' => 'hogehoge'
        ];
        $smarty->assign($replacement);
        $template = $smarty->fetch('string:'.$source); // $sourceはデータベースに保存された本文
        return $this->from($this->data['email'], $this->data['name'])
            ->subject('件名')
            ->text('emails.email')
            ->with(['context' => $template]);
    }
}

bladeテンプレート側は、変数一個だけ用意して

ビジネスロジックからメール本文をゴッソリ変数で渡すだけ。

メール本文の数だけbladeテンプレートを作る必要が無い場合は

こんな方法もアリっちゃアリなのかな。

masa