跳转到主要内容

什么是 Notification

Laravel 的通知(Notification)系统提供了统一的 API,可以向邮件、SMS、Slack、数据库等多个渠道发送通知。 Mail 与 Notification 的区别
比较MailNotification
主要用途富文本 HTML 邮件简短的信息通知
支持渠道仅邮件邮件、DB、Slack、SMS 等多种
模板完全自由简单的消息格式
像“发票已支付”这类需要向多个渠道发送同一条通知的场景,Notification 更合适。

创建 Notification 类

使用 make:notification Artisan 命令生成通知类。
php artisan make:notification InvoicePaid
生成的类位于 app/Notifications/。类中包含 via() 方法以及为各个渠道生成消息的方法。

发送通知的方式

使用 Notifiable trait

App\Models\User 默认已经包含了 Notifiable trait,可以用 notify() 方法发送通知。
use App\Notifications\InvoicePaid;

$user->notify(new InvoicePaid($invoice));
Notifiable trait 并不限于 User 模型,任何模型都可以添加它。

使用 Notification Facade

要同时向多个用户发送,可以使用 Notification Facade。
use Illuminate\Support\Facades\Notification;

Notification::send($users, new InvoicePaid($invoice));
要立即发送(跳过队列),可以使用 sendNow()
Notification::sendNow($developers, new DeploymentCompleted($deployment));

指定发送渠道

via() 方法以数组形式返回要使用的渠道。
public function via(object $notifiable): array
{
    return ['mail', 'database'];
}
也可以根据用户偏好切换渠道。
public function via(object $notifiable): array
{
    return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}
主要可用渠道如下。
渠道键名说明
邮件mail通过邮件发送通知
数据库database保存到数据库,在 UI 中展示
广播broadcast实时通知(WebSocket)
SMSvonage通过 Vonage(原 Nexmo)发送短信
Slackslack发送到 Slack 频道

邮件渠道通知

toMail() 方法返回一个 MailMessage 实例。
use Illuminate\Notifications\Messages\MailMessage;

public function toMail(object $notifiable): MailMessage
{
    $url = url('/invoice/'.$this->invoice->id);

    return (new MailMessage)
        ->greeting('你好!')
        ->line('我们已收到你的发票付款。')
        ->action('查看发票', $url)
        ->line('感谢你的使用。');
}
MailMessage 的常用方法如下:
方法说明
greeting()开头问候语
line()一行正文
action()按钮链接
subject()主题
from()发件人地址
mailer()使用的 mailer
如果是错误通知,可以加上 error(),按钮会变红。
return (new MailMessage)
    ->error()
    ->subject('支付失败')
    ->line('发票支付处理失败。');

Markdown 通知邮件

也可以使用 Markdown 编写更丰富的邮件。加上 --markdown 选项生成类。
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
使用 toMarkdownMail() 代替 toMail()
use Illuminate\Notifications\Messages\MailMessage;

public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
        ->markdown('mail.invoice.paid', [
            'url' => url('/invoice/'.$this->invoice->id),
            'invoice' => $this->invoice,
        ]);
}

数据库渠道通知

数据库渠道可以把通知保存到数据库,并在应用 UI 中展示。

准备表结构

先创建 notifications 表。
php artisan make:notifications-table

php artisan migrate

定义 toArray 方法

toArray() 方法以数组形式返回要保存的数据。
public function toArray(object $notifiable): array
{
    return [
        'invoice_id' => $this->invoice->id,
        'amount' => $this->invoice->amount,
        'message' => '我们已收到你的发票付款。',
    ];
}
这些数据会以 JSON 存放在 notifications 表的 data 列中。

获取通知

Notifiable trait 提供 notifications 关联,可用于读取通知。
$user = App\Models\User::find(1);

foreach ($user->notifications as $notification) {
    echo $notification->type;
    echo $notification->data['message'];
}
要只获取未读通知,使用 unreadNotifications
foreach ($user->unreadNotifications as $notification) {
    echo $notification->data['message'];
}

标记为已读

使用 markAsRead() 将通知标为已读。
// 逐条标记
foreach ($user->unreadNotifications as $notification) {
    $notification->markAsRead();
}

// 一次性全部标记
$user->unreadNotifications->markAsRead();

// 使用查询批量更新
$user->unreadNotifications()->update(['read_at' => now()]);

通知的队列化

如果通知发送耗时较长,可以实现 ShouldQueue 接口并使用 Queueable trait,将通知放到队列中。make:notification 生成的类默认已经导入了它们。
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;

class InvoicePaid extends Notification implements ShouldQueue
{
    use Queueable;

    // ...
}
实现 ShouldQueue 后,调用 notify() 时通知会自动进入队列。
$user->notify(new InvoicePaid($invoice));
也支持延迟发送。
$user->notify(
    (new InvoicePaid($invoice))->delay(now()->plus(minutes: 10))
);

同时向多个渠道发送

只要在 via() 中返回多个渠道并各自定义方法,就可以同时向多个渠道发送同一条通知。
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class InvoicePaid extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        private readonly Invoice $invoice,
    ) {}

    public function via(object $notifiable): array
    {
        // 同时发送到邮件和数据库
        return ['mail', 'database'];
    }

    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject('我们已收到你的发票付款')
            ->line('已确认收到发票 #'.$this->invoice->id.' 的付款。')
            ->action('查看发票', url('/invoice/'.$this->invoice->id));
    }

    public function toArray(object $notifiable): array
    {
        return [
            'invoice_id' => $this->invoice->id,
            'amount' => $this->invoice->amount,
        ];
    }
}

按需通知(On-demand notifications)

要向没有账号的人发送通知,可以使用 Notification::route()
use Illuminate\Support\Facades\Notification;

Notification::route('mail', '[email protected]')
    ->route('vonage', '5555551212')
    ->notify(new InvoicePaid($invoice));

小结

想做的事方法
创建 Notificationphp artisan make:notification ClassName
向用户发送通知$user->notify(new MyNotification())
向多个用户发送Notification::send($users, new MyNotification())
使用邮件发送via() 中返回 mail 并定义 toMail()
保存到数据库via() 中返回 database 并定义 toArray()
使用队列异步发送实现 ShouldQueue
发送到多个渠道via() 中返回多个键
最后修改于 2026年7月13日