はじめに
ユーザー招待機能の詳細設計と実装(3) 招待メール送信処理 について投稿します。
Web業界実務未経験での転職活動用にポートフォリオとしてはじめて作成したWebアプリ開発のオリジナルの機能として 家族ユーザー招待機能 を実装したときのものです。
※ 作成したポートフォリオは、絵本を読み聞かせしたことの記録・管理を、家族と共有できるWebアプリケーションです(作成期間は、2021年2月末〜7月)
投稿内容(全5回)
本連載は以下の順番で投稿します。
- 招待ユーザー機能の概要と基本設計
- 招待ユーザー機能の詳細設計と実装
今回は、ユーザー招待機能の詳細設計と実装(3) 招待メール送信処理 についてです。
目次
以下、本記事の目次です。
使用技術、サービスなど
- PHP 7.4.13
- Laravel 6.20.20
- MySQL 8.0.23
- MailHog(開発者向けのメールテストツール、開発環境)
1. Mailable クラスを継承したクラスの作成
Mailable
クラスを継承した BareMail
クラスを作成します。
Laravel では、メールを取り扱うクラスが複数ありますが、Mailable
クラスを利用します。Mailable
クラスを選択する理由は、 HTML メールではなくテキストメールを送るにはMailable
クラスを使う必要があるためです。
(このアプリの作成の際は「メールを利用したパスワード再設定」機能追加時に作成したファイルを、家族招待通知でも再利用しました。)
1-1. BareMail.php の作成
以下コマンドを実行して、 backend/app/Mail/ ディレクトリ以下に、 BareMail.php を作成します。
docker-compose exec app php artisan make:mail BareMail
1-2. BareMail.php の編集
作成されたファイルを編集します。
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class BareMail extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this;
}
}
メールの種類ごとの細かい設定は持たせず、空の設定のメールとして使用していくため、 build
メソッドでは何も設定せず、そのまま自分自身を返します。
宛先や件名、使用するテンプレートなどは、次に作成する通知クラスで設定します。
2. 通知クラスの作成
通知クラス(InvitationFamilyNotification
クラス)を作成し、 BareMail
クラスを用いたメール送信メソッドを追加します。
2-1. InvitationFamilyNotification.php の作成
以下コマンドを実行して、 backend/app/Notifications/ ディレクトリ以下に、 InvitationFamilyNotification.php を作成します。
docker-compose exec app php artisan make:notification InvitationFamilyNotification
2-2. InvitationFamilyNotification.php の編集
作成されたファイルを編集します。
<?php
namespace App\Notifications;
use App\Mail\BareMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class InvitationFamilyNotification extends Notification
{
use Queueable;
public $token;
public $mail;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct(string $token, BareMail $mail)
{
$this->token = $token;
$this->mail = $mail;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \\Illuminate\\Notifications\\Messages\\MailMessage
*/
public function toMail($notifiable)
{
return $this->mail
->from(config('mail.from.address'), config('mail.from.name'))
->to($notifiable->email)
->subject('[よんで] 家族招待')
->text('emails.invite')
->with([
'url' => route('register.invited.{token}', [
'token' => $notifiable->token,
]),
]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
2-3. 参考
コンストラクタインジェクション
クラスのインスタンスをコンストラクタで注入(DI)することを、コンストラクタインジェクションと言う。
public $token;
public $mail;
InvitationFamilyNotification
クラスに $token
プロパティと $mail
プロパティを定義している。
public function __construct(string $token, BareMail $mail)
{
$this->token = $token;
$this->mail = $mail;
}
__construct
メソッドで、引数として、文字列の $token
と、BaraMail
クラスのインスタンスの $mail
を、それぞれプロパティに代入している。
toMail メソッド
toMail
メソッド内で、メールの具体的な設定を行なっている。
public function toMail($notifiable)
{
return $this->mail
->from(config('mail.from.address'), config('mail.from.name'))
->to($notifiable->email)
->subject('[よんで] 家族招待')
->text('emails.invite')
->with([
'url' => route('register.invited.{token}', [
'token' => $notifiable->token,
]),
]);
}
from メソッド
Mailable
クラスの from
メソッドに以下の引数を渡す。
- 第一引数には、送信元メールアドレス
- 第二引数には、メールの送信者名(省略可)
引数については、config
関数を使って、 backend/config/mail.php の以下の値を取得している。
<?php
return [
// 略
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
// 略
];
address
、name
それぞれについて、 env
関数を使って取得した環境変数の値になっている。( env
関数の第二引数は、第一引数の環境変数が存在しない場合のデフォルト値)
- 確認:backend/.env
APP_NAME=Yonde
# 省略
MAIL_FROM_NAME="${APP_NAME}"
MAIL_FROM_ADDRESS=no-reply@example.com
to メソッド
->to($notifiable->email)
to
メソッドには、送信先メールアドレスを渡す。
$notifiable
には、メール送信先となる User
モデルが代入されているので、 $notifiable->email
で、メール送信先ユーザーのメールアドレスを取得している。
subject メソッド
->subject('[よんで] 家族招待')
subject
メソッドには、メールの件名を渡す。
text メソッド
->text('emails.invite')
text
メソッドは、テキスト形式のメールを送る場合に使うメソッド。
引数で、メールのテンプレートを指定する。 'emails.invite'
とすることで、backend/resources/views/emails/ ディレクトリの invite.blade.php がテンプレートとして使用される。
with メソッド
->with([
'url' => route('register.invited.{token}', [
'token' => $notifiable->token,
]),
テンプレートとなる Blade に渡す変数を、 with
メソッドに連想配列形式で渡す。
キー url
の値には、 route
関数を使って register.invited.{token}
のルーティングをセットしている。
-
register.invited.{token}
のルーティングは、以下のとおり。
+--------+-----------+-----------------------------------+--------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+-----------------------------------+--------------------------------+-------------------------------------------------------------------------------+------------------------------------------------------+
// 略
| | GET|HEAD | register/invited/{token} | register.invited.{token} | App\\Http\\Controllers\\Auth\\RegisterController@showInvitedUserRegistrationForm | web,guest |
// 略
3. Invite モデルへのメソッドの追加
Invite モデルを作成して、メソッドを追加します。
3-1. Invite モデルの作成
下記コマンドを実行して、Invite モデルを作成します。
以下コマンドを実行して、 backend/app/ ディレクトリ以下に、 Invite.php を作成します。
docker-compose exec app php artisan make:model Invite
3-2. Invite モデルへのメソッドの追加
Invite モデルに sendInvitationFamilyNotification
メソッドを定義します。
<?php
namespace App;
use App\Mail\BareMail;
use Illuminate\Database\Eloquent\Model;
use App\Notifications\InvitationFamilyNotification;
use Illuminate\Notifications\Notifiable;
class Invite extends Model
{
use Notifiable;
protected $fillable = [
'family_id',
'email',
'token',
];
// 家族招待通知送信
public function sendInvitationFamilyNotification($token)
{
$this->notify(new InvitationFamilyNotification($token, new BareMail()));
}
}
先ほど作成した通知クラスである InvitationFamilyNotification
クラスのインスタンスを生成して、 notify
メソッドに渡すことにより、次で作成するテキストメールが家族ユーザー招待メールとして送信されるようになります。
おわりに
今回は、招待ユーザー機能の詳細設計と実装(3) 招待メール送信処理 についてでした。
次回は、 (4) 招待メールのテンプレート についてです。
ありがとうございました。