【Laravel】メールによる通知機能を実装する|簡単な掲示板アプリの作成

Laravelの便利な通知(Notification)機能を使って、メール送信を実装する方法を解説します。掲示板アプリを題材に、自分の投稿にコメントや「いいね」がついた際に、投稿者へ自動でメールが届く仕組みを作ります。通知クラスの作成方法からコントローラーでの使い方、.envファイルでのSMTP設定までを学べます。

作成日: 更新日:

開発環境

  • OS: Windows10
  • Visual Studio Code: 1.73.0
  • PHP: 8.3.11
  • Laravel: 11.29.0
  • laravel/breeze: 2.2

サンプルコード

.env

.env
1MAIL_MAILER=smtp
2MAIL_HOST=smtp.gmail.com
3MAIL_PORT=587
4MAIL_USERNAME=xxxxxx@gmail.com
5MAIL_PASSWORD=xxxxxxxxxxxxxx
6MAIL_ENCRYPTION=tls
7MAIL_FROM_ADDRESS=xxxxxx@gmail.com
8MAIL_FROM_NAME="${APP_NAME}"

/app/Http/Controllers/CommentController.php

/app/Http/Controllers/CommentController.php
1 use App\Models\Post;
2 use Illuminate\Http\Request;
3 use Illuminate\Support\Facades\Auth;
4+use App\Notifications\CommentNotification;
5 
6 class CommentController extends Controller
7 {
8             'content' => $request->content,
9         ]);
10 
11+        // 投稿者に通知を送信
12+        $post->user->notify(new CommentNotification($post));
13+
14         return redirect()->route('posts.show', $post->id);
15     }
16 }
17

/app/Http/Controllers/LikeController.php

/app/Http/Controllers/LikeController.php
1 use Illuminate\Http\Request;
2 use App\Models\Post;
3 use Illuminate\Support\Facades\Auth;
4+use App\Notifications\LikeNotification;
5 
6 class LikeController extends Controller
7 {
8     public function toggleLike(Post $post)
9     {
10-
11         // ログインしていなければ、ログインページにリダイレクト
12         if (!auth()->check()) {
13             return redirect()->route('login');
14         } else {
15             // いいねを追加
16             $post->likes()->create(['user_id' => $user->id]);
17+
18+            // 投稿者に通知を送信
19+            $post->user->notify(new LikeNotification($post));
20         }
21 
22         return redirect()->back();
23

/app/Models/Post.php

/app/Models/Post.php
1     {
2         return $this->hasMany(Like::class);
3     }
4+
5+    public function user()
6+    {
7+        return $this->belongsTo(User::class);
8+    }
9 }
10

/app/Notifications/CommentNotification.php

/app/Notifications/CommentNotification.php
1+<?php
2+
3+namespace App\Notifications;
4+
5+use Illuminate\Bus\Queueable;
6+use Illuminate\Contracts\Queue\ShouldQueue;
7+use Illuminate\Notifications\Messages\MailMessage;
8+use Illuminate\Notifications\Notification;
9+use App\Models\Post;
10+
11+class CommentNotification extends Notification
12+{
13+    use Queueable;
14+
15+    protected $post;
16+
17+    /**
18+     * Create a new notification instance.
19+     */
20+    public function __construct(Post $post)
21+    {
22+        $this->post = $post;
23+    }
24+
25+    /**
26+     * Get the notification's delivery channels.
27+     *
28+     * @return array<int, string>
29+     */
30+    public function via(object $notifiable): array
31+    {
32+        return ['mail'];
33+    }
34+
35+    /**
36+     * Get the mail representation of the notification.
37+     */
38+    public function toMail(object $notifiable): MailMessage
39+    {
40+        return (new MailMessage)
41+                ->subject('あなたの投稿に新しいコメントがありました')
42+                ->line('あなたの投稿に新しいコメントがつきました!')
43+                ->action('投稿を確認する', route('posts.show', $this->post->id))
44+                ->line('ご利用ありがとうございます!');
45+    }
46+
47+    /**
48+     * Get the array representation of the notification.
49+     *
50+     * @return array<string, mixed>
51+     */
52+    public function toArray(object $notifiable): array
53+    {
54+        return [
55+            //
56+        ];
57+    }
58+}
59

/app/Notifications/LikeNotification.php

/app/Notifications/LikeNotification.php
1+<?php
2+
3+namespace App\Notifications;
4+
5+use Illuminate\Bus\Queueable;
6+use Illuminate\Contracts\Queue\ShouldQueue;
7+use Illuminate\Notifications\Messages\MailMessage;
8+use Illuminate\Notifications\Notification;
9+use App\Models\Post;
10+
11+class LikeNotification extends Notification
12+{
13+    use Queueable;
14+
15+    protected $post;
16+
17+    /**
18+     * Create a new notification instance.
19+     */
20+    public function __construct(Post $post)
21+    {
22+        $this->post = $post;
23+    }
24+
25+    /**
26+     * Get the notification's delivery channels.
27+     *
28+     * @return array<int, string>
29+     */
30+    public function via(object $notifiable): array
31+    {
32+        return ['mail'];
33+    }
34+
35+    /**
36+     * Get the mail representation of the notification.
37+     */
38+    public function toMail(object $notifiable): MailMessage
39+    {
40+        return (new MailMessage)
41+                ->subject('あなたの投稿にいいねがありました')
42+                ->line('あなたの投稿にいいねがつきました!')
43+                ->action('投稿を確認する', route('posts.show', $this->post->id))
44+                ->line('ご利用ありがとうございます!');
45+    }
46+
47+    /**
48+     * Get the array representation of the notification.
49+     *
50+     * @return array<string, mixed>
51+     */
52+    public function toArray(object $notifiable): array
53+    {
54+        return [
55+            //
56+        ];
57+    }
58+}
59

コード解説

変更点: メールの送信設定(SMTP)

.env
1MAIL_MAILER=smtp
2MAIL_HOST=smtp.gmail.com
3MAIL_PORT=587
4MAIL_USERNAME=xxxxxx@gmail.com
5MAIL_PASSWORD=xxxxxxxxxxxxxx
6MAIL_ENCRYPTION=tls
7MAIL_FROM_ADDRESS=xxxxxx@gmail.com
8MAIL_FROM_NAME="${APP_NAME}"

.envファイルは、Laravelアプリケーションの環境設定を管理するファイルです。ここにメール送信に関する設定を記述します。今回はGmailのSMTPサーバーを利用してメールを送信する設定例です。

  • MAIL_MAILER: メールの送信方法を指定します。smtpは、SMTPサーバーを経由してメールを送信する方法です。
  • MAIL_HOST: 使用するSMTPサーバーのホスト名(アドレス)を指定します。Gmailの場合はsmtp.gmail.comです。
  • MAIL_PORT: SMTPサーバーが使用するポート番号を指定します。587はTLS暗号化で推奨されるポートです。
  • MAIL_USERNAME: SMTPサーバーにログインするためのユーザー名(Gmailアドレス)です。
  • MAIL_PASSWORD: SMTPサーバーにログインするためのパスワードです。Gmailの場合、通常のログインパスワードではなく、セキュリティ設定から生成される「アプリパスワード」を設定する必要があります。
  • MAIL_ENCRYPTION: 通信を暗号化する方法を指定します。tlsは安全な通信を確立するための一般的なプロトコルです。
  • MAIL_FROM_ADDRESS: 送信元として表示されるメールアドレスです。
  • MAIL_FROM_NAME: 送信元として表示される名前です。${APP_NAME}と記述すると、同じ.envファイル内のAPP_NAMEの値が自動的に使われます。

変更点: コメント通知クラスの作成

/app/Notifications/CommentNotification.php
1+<?php
2+
3+namespace App\Notifications;
4+
5+use Illuminate\Bus\Queueable;
6+use Illuminate\Contracts\Queue\ShouldQueue;
7+use Illuminate\Notifications\Messages\MailMessage;
8+use Illuminate\Notifications\Notification;
9+use App\Models\Post;
10+
11+class CommentNotification extends Notification
12+{
13+    use Queueable;
14+
15+    protected $post;
16+
17+    public function __construct(Post $post)
18+    {
19+        $this->post = $post;
20+    }
21+
22+    public function via(object $notifiable): array
23+    {
24+        return ['mail'];
25+    }
26+
27+    public function toMail(object $notifiable): MailMessage
28+    {
29+        return (new MailMessage)
30+                ->subject('あなたの投稿に新しいコメントがありました')
31+                ->line('あなたの投稿に新しいコメントがつきました!')
32+                ->action('投稿を確認する', route('posts.show', $this->post->id))
33+                ->line('ご利用ありがとうございます!');
34+    }
35+
36+    public function toArray(object $notifiable): array
37+    {
38+        return [
39+            //
40+        ];
41+    }
42+}

これは、コメントが投稿された際に送信されるメールの内容や設定を定義する「通知クラス」です。php artisan make:notification CommentNotificationというコマンドで雛形を生成できます。

  • __construct(Post $post): このクラスが作られるときに、どの投稿に対する通知なのかを情報として受け取ります。受け取った投稿情報($post)をクラス内の変数$this->postに保存しています。
  • via(): この通知をどのような方法(チャネル)で送信するかを定義します。['mail']と返すことで、メールで送信することを指定しています。他にもSlackやSMSなど様々なチャネルが利用可能です。
  • toMail(): メールで送信する場合の、具体的な内容を組み立てるメソッドです。MailMessageオブジェクトを使って、流れるように設定を記述できます。
    • subject(): メールの件名を指定します。
    • line(): メールの本文を1行ずつ追加します。
    • action(): メール内に表示されるボタンのテキストと、クリックした際のURLを指定します。ここではroute('posts.show', $this->post->id)とすることで、通知の対象となった投稿の詳細ページへのリンクを生成しています。

変更点: いいね通知クラスの作成

/app/Notifications/LikeNotification.php
1+<?php
2+
3+namespace App\Notifications;
4+
5+use Illuminate\Bus\Queueable;
6+use Illuminate\Contracts\Queue\ShouldQueue;
7+use Illuminate\Notifications\Messages\MailMessage;
8+use Illuminate\Notifications\Notification;
9+use App\Models\Post;
10+
11+class LikeNotification extends Notification
12+{
13+    use Queueable;
14+
15+    protected $post;
16+
17+    public function __construct(Post $post)
18+    {
19+        $this->post = $post;
20+    }
21+
22+    public function via(object $notifiable): array
23+    {
24+        return ['mail'];
25+    }
26+
27+    public function toMail(object $notifiable): MailMessage
28+    {
29+        return (new MailMessage)
30+                ->subject('あなたの投稿にいいねがありました')
31+                ->line('あなたの投稿にいいねがつきました!')
32+                ->action('投稿を確認する', route('posts.show', $this->post->id))
33+                ->line('ご利用ありがとうございます!');
34+    }
35+
36+    public function toArray(object $notifiable): array
37+    {
38+        return [
39+            //
40+        ];
41+    }
42+}

これは、投稿に「いいね」がついた際に送信される通知クラスです。基本的な構造は先ほどのCommentNotificationと全く同じです。toMailメソッド内のsubject(件名)やline(本文)の文言を、「いいね」があったことが伝わる内容に変更している点が主な違いです。このように、通知の種類ごとにクラスを分けることで、管理がしやすくなります。

変更点: PostモデルとUserモデルのリレーション定義

/app/Models/Post.php
1+    public function user()
2+    {
3+        return $this->belongsTo(User::class);
4+    }

Postモデル(投稿データを扱うクラス)に、userメソッドを追加しました。これは、EloquentというLaravelの機能を使った「リレーション(関連付け)」の定義です。

belongsTo(User::class)と記述することで、「一つの投稿(Post)は、一人のユーザー(User)に属している」という関係をLaravelに教えています。

この設定により、コントローラーなどで投稿データを取得した際に、$post->userという簡単な記述で、その投稿を作成したユーザーの情報を簡単に入手できるようになります。今回の通知機能では、「誰が投稿したのか」という情報が必要になるため、このリレーション定義が不可欠です。

変更点: コメント作成時に通知を送信

/app/Http/Controllers/CommentController.php
1 use App\Models\Post;
2 use Illuminate\Http\Request;
3 use Illuminate\Support\Facades\Auth;
4+use App\Notifications\CommentNotification;
5 
6 class CommentController extends Controller
7 {
8     public function store(Request $request, Post $post)
9     {
10         // (コメント保存処理...)
11 
12+        // 投稿者に通知を送信
13+        $post->user->notify(new CommentNotification($post));
14+
15         return redirect()->route('posts.show', $post->id);
16     }
17 }

コメントを保存する処理が書かれているCommentControllerに、通知を送信する機能を追加しました。

  • use App\Notifications\CommentNotification;: まず、先ほど作成したコメント用の通知クラスをこのファイルで使えるように読み込んでいます。
  • $post->user->notify(new CommentNotification($post));: この1行が通知を送信する処理の本体です。
    • $post->user: Postモデルに定義したリレーションを使い、コメントが投稿された投稿($post)の作成者(user)を取得しています。
    • ->notify(...): Userモデルが持つ通知送信メソッドです。このメソッドの引数に通知クラスのインスタンスを渡すことで、指定したユーザーに通知が送られます。
    • new CommentNotification($post): コメント用の通知クラスのインスタンスを作成しています。コンストラクタに$postを渡すことで、メール本文内で投稿情報を使えるようにしています。

つまり、コメントがデータベースに保存された直後に、その投稿の作成者に対して「コメントがつきましたよ」という通知メールを送る処理が実現できています。

変更点: いいね作成時に通知を送信

/app/Http/Controllers/LikeController.php
1 use Illuminate\Http\Request;
2 use App\Models\Post;
3 use Illuminate\Support\Facades\Auth;
4+use App\Notifications\LikeNotification;
5 
6 class LikeController extends Controller
7 {
8     public function toggleLike(Post $post)
9     {
10         // (いいね保存処理...)
11             $post->likes()->create(['user_id' => $user->id]);
12+
13+            // 投稿者に通知を送信
14+            $post->user->notify(new LikeNotification($post));
15         }
16 
17         return redirect()->back();

いいねを保存するLikeControllerにも、同様に通知機能を追加しました。

  • use App\Notifications\LikeNotification;: いいね用の通知クラスを読み込みます。
  • $post->user->notify(new LikeNotification($post));: 投稿の作成者($post->user)に対して、いいね通知クラス(LikeNotification)を使って通知を送信しています。

処理の流れはコメント通知と全く同じです。どの通知クラスを使うかを入れ替えるだけで、異なる内容のメールを送信できるのが、Laravelの通知機能の便利な点です。これにより、「いいね」がついたタイミングで、投稿者にリアルタイムで通知メールが届くようになりました。

おわりに

今回はLaravelの通知機能を使って、コメントやいいねといったアクションをきっかけにメールを送信する方法を学びました。CommentNotificationのように通知内容を定義したクラスを作成し、toMailメソッドで件名や本文を自由に設定できることが分かりましたね。コントローラー側では$post->user->notify()という1行のコードを追加するだけで通知を送信でき、その手軽さを実感できたのではないでしょうか。この仕組みは.envファイルでのメールサーバー設定が土台となっているため、忘れずに設定するようにしましょう。

関連コンテンツ