#22 Laravel基礎

通知(Notification)機能

MailableとNotificationの違い

MailableNotification
チャンネルメールのみメール・DB・Slack・SMSなど複数
宛先メールアドレスユーザーモデル
向いている場面独立したメール「イベント→通知」のパターン

通知(Notification)は「誰かがコメントした」「支払いが完了した」のようなアクションへの反応を、複数のチャンネルに送りたい場合に向いています。


Notificationを生成する

php artisan make:notification CommentPosted

app/Notifications/CommentPosted.php が生成されます。

<?php
// 📁 app/Notifications/CommentPosted.php

namespace App\Notifications;

use App\Models\Comment;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class CommentPosted extends Notification
{
    use Queueable;

    public function __construct(
        public Comment $comment
    ) {}

    // 使用するチャンネルを指定
    public function via(object $notifiable): array
    {
        return ['mail', 'database']; // メールとDBに送る
    }

    // メールチャンネルの内容
    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject('あなたの投稿にコメントが届きました')
            ->greeting("{$notifiable->name} さん")
            ->line("{$this->comment->user->name} さんがコメントしました。")
            ->line("\"{$this->comment->body}\"")
            ->action('コメントを確認する', route('posts.show', $this->comment->post_id))
            ->line('ご確認ください。');
    }

    // データベースチャンネルの内容(通知テーブルに保存)
    public function toDatabase(object $notifiable): array
    {
        return [
            'comment_id' => $this->comment->id,
            'post_id'    => $this->comment->post_id,
            'commenter'  => $this->comment->user->name,
            'body'       => $this->comment->body,
        ];
    }
}

通知テーブルを作成する

データベースチャンネルを使う場合は通知テーブルが必要です。

php artisan notifications:table
php artisan migrate

通知を送る

// 📁 app/Http/Controllers/CommentController.php

use App\Notifications\CommentPosted;

public function store(Request $request, Post $post)
{
    $comment = $post->comments()->create([
        'body'    => $request->body,
        'user_id' => auth()->id(),
    ]);

    // 投稿者($post->user)に通知を送る
    $post->user->notify(new CommentPosted($comment));

    return redirect()->back();
}

notify() メソッドはモデルに Notifiable トレイトが含まれていれば使えます(User モデルは最初から含まれています)。


複数のユーザーに通知を送る(Facade使用)

use Illuminate\Support\Facades\Notification;

// 複数のユーザーにまとめて通知
Notification::send($users, new CommentPosted($comment));

未読通知を表示する

// 📁 app/Http/Controllers/NotificationController.php

public function index()
{
    $user = auth()->user();

    // 未読の通知一覧
    $unreadNotifications = $user->unreadNotifications;

    // 全通知一覧
    $allNotifications = $user->notifications;

    // 未読を既読にする
    $user->unreadNotifications->markAsRead();

    return view('notifications.index', compact('allNotifications'));
}
{{-- ヘッダーに未読数バッジを表示する例 --}}
@auth
    @if (auth()->user()->unreadNotifications->count() > 0)
        <span class="badge">{{ auth()->user()->unreadNotifications->count() }}</span>
    @endif
@endauth

キューで非同期送信する

// ShouldQueue を追加するだけでキュー経由になる
class CommentPosted extends Notification implements \Illuminate\Contracts\Queue\ShouldQueue
{
    use Queueable;
    // ...
}

まとめ

  • via() で使用するチャンネル(mail, database など)を指定する
  • toMail() でメールの内容を MailMessage で組み立てる
  • toDatabase() で通知データを配列で返す
  • $user->notify() または Notification::send() で送信する
  • $user->unreadNotifications で未読通知を取得できる

次回はAPI認証(Laravel Sanctum)を学びます。