Notifications

Introduction

除了支持发送电子邮件, Laravel 支持通过各种传递渠道发送通知,包括电子邮件、SMS(通过Vonage,以前称为 Nexmo)和Slack.此外,各种社区建立的通知渠道 已创建用于通过数十种不同渠道发送通知!通知也可能存储在数据库中,因此它们可能会显示在您的网络界面中。

通常,通知应该是简短的信息性消息,通知用户您的应用程序中发生的事情。例如,如果您正在编写计费应用程序,您可能会通过电子邮件和 SMS 渠道向您的用户发送“发票已付”通知。

生成通知

在 Laravel 中,每个通知都由一个类表示,该类通常存储在app/Notifications 目录。如果您在应用程序中没有看到此目录,请不要担心 - 它会在您运行时为您创建make:notification 工匠命令:

php artisan make:notification InvoicePaid

此命令将在您的app/Notifications 目录。每个通知类包含一个via 方法和可变数量的消息构建方法,例如toMail 或者toDatabase,将通知转换为为该特定频道量身定制的消息。

发送通知

使用通知特征

通知可以通过两种方式发送:使用notify 的方法Notifiable 特征或使用Notification facade.这Notifiable 特征包含在您的应用程序中App\Models\User 默认型号:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
}

notify 此特征提供的方法期望接收通知实例:

use App\Notifications\InvoicePaid;

$user->notify(new InvoicePaid($invoice));

Note
请记住,您可以使用Notifiable 任何模型的特征。您不仅限于将其包含在您的User 模型。

使用通知外观

或者,您可以通过以下方式发送通知Notification facade.当您需要向多个可通知实体(例如一组用户)发送通知时,此方法很有用。要使用外观发送通知,请将所有可通知实体和通知实例传递给send方法:

use Illuminate\Support\Facades\Notification;

Notification::send($users, new InvoicePaid($invoice));

您还可以使用sendNow 方法。此方法将立即发送通知,即使通知实现了ShouldQueue 界面:

Notification::sendNow($developers, new DeploymentCompleted($deployment));

指定交付渠道

每个通知类都有一个via 确定通知将传递到哪些渠道的方法。通知可发送至mail,database,broadcast,vonage, 和slack 渠道。

Note
如果您想使用其他交付渠道,例如 Telegram 或 Pusher,请查看社区驱动Laravel 通知通道网站.

via 方法接收一个$notifiable instance,它将是通知被发送到的类的一个实例。你可以使用$notifiable 确定应在哪些渠道上发送通知:

/**
 * Get the notification's delivery channels.
 *
 * @return array<int, string>
 */
public function via(object $notifiable): array
{
    return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}

排队通知

Warning
在排队通知之前,您应该配置您的队列和开始一个工人.

发送通知可能需要时间,尤其是当通道需要调用外部 API 来传递通知时。要加快应用程序的响应时间,请通过添加ShouldQueue 接口和Queueable 你班级的特质。已经为使用生成的所有通知导入了接口和特征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 接口已添加到您的通知中,您可以像往常一样发送通知。 Laravel 会检测到ShouldQueue 类上的接口并自动排队通知的传递:

$user->notify(new InvoicePaid($invoice));

排队通知时,将为每个收件人和频道组合创建一个排队的作业。例如,如果您的通知有三个收件人和两个频道,则六个作业将被分派到队列中。

延迟通知

如果您想延迟通知的发送,您可以链接delay 方法到您的通知实例化:

$delay = now()->addMinutes(10);

$user->notify((new InvoicePaid($invoice))->delay($delay));

每个频道的延迟通知

您可以将一个数组传递给delay 为特定通道指定延迟量的方法:

$user->notify((new InvoicePaid($invoice))->delay([
    'mail' => now()->addMinutes(5),
    'sms' => now()->addMinutes(10),
]));

或者,您可以定义一个withDelay 通知类本身的方法。这withDelay 方法应返回一组通道名称和延迟值:

/**
 * Determine the notification's delivery delay.
 *
 * @return array<string, \Illuminate\Support\Carbon>
 */
public function withDelay(object $notifiable): array
{
    return [
        'mail' => now()->addMinutes(5),
        'sms' => now()->addMinutes(10),
    ];
}

自定义通知队列连接

默认情况下,排队的通知将使用应用程序的默认队列连接进行排队。如果你想指定一个不同的连接用于特定的通知,你可以定义一个$connection 通知类的属性:

/**
 * The name of the queue connection to use when queueing the notification.
 *
 * @var string
 */
public $connection = 'redis';

或者,如果您想指定一个特定的队列连接,该连接应该用于通知支持的每个通知通道,您可以定义一个viaConnections 通知上的方法。此方法应返回通道名称/队列连接名称对的数组:

/**
 * Determine which connections should be used for each notification channel.
 *
 * @return array<string, string>
 */
public function viaConnections(): array
{
    return [
        'mail' => 'redis',
        'database' => 'sync',
    ];
}

自定义通知通道队列

如果你想为通知支持的每个通知通道指定一个特定的队列,你可以定义一个viaQueues 通知上的方法。此方法应返回通道名称/队列名称对的数组:

/**
 * Determine which queues should be used for each notification channel.
 *
 * @return array<string, string>
 */
public function viaQueues(): array
{
    return [
        'mail' => 'mail-queue',
        'slack' => 'slack-queue',
    ];
}

排队通知和数据库事务

在数据库事务中调度排队通知时,它们可能在数据库事务提交之前由队列处理。发生这种情况时,您在数据库事务期间对模型或数据库记录所做的任何更新可能尚未反映在数据库中。此外,在事务中创建的任何模型或数据库记录可能不存在于数据库中。如果您的通知依赖于这些模型,则在处理发送排队通知的作业时可能会发生意外错误。

如果您的队列连接的after_commit 配置选项设置为false,您仍然可以通过调用afterCommit 发送通知时的方法:

use App\Notifications\InvoicePaid;

$user->notify((new InvoicePaid($invoice))->afterCommit());

或者,您可以致电afterCommit 通知构造函数中的方法:

<?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;

    /**
     * Create a new notification instance.
     */
    public function __construct()
    {
        $this->afterCommit();
    }
}

Note
要了解有关解决这些问题的更多信息,请查看有关的文档排队作业和数据库事务.

确定是否应发送排队的通知

在为队列分派队列通知以进行后台处理后,它通常会被队列工作者接受并发送给它的预期接收者。

然而,如果你想最终决定是否应该在队列工作者处理后发送排队的通知,你可以定义一个shouldSend 通知类上的方法。如果此方法返回false,将不会发送通知:

/**
 * Determine if the notification should be sent.
 */
public function shouldSend(object $notifiable, string $channel): bool
{
    return $this->invoice->isPaid();
}

按需通知

有时您可能需要向未存储为应用程序“用户”的人发送通知。使用Notification 门面的route 方法,您可以在发送通知之前指定临时通知路由信息:

use Illuminate\Broadcasting\Channel;

Notification::route('mail', 'taylor@example.com')
            ->route('vonage', '5555555555')
            ->route('slack', 'https://hooks.slack.com/services/...')
            ->route('broadcast', [new Channel('channel-name')])
            ->notify(new InvoicePaid($invoice));

如果您想在将按需通知发送到mail 路由,您可以提供一个数组,其中包含电子邮件地址作为键,名称作为数组中第一个元素的值:

Notification::route('mail', [
    'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));

邮件通知

格式化邮件消息

如果通知支持作为电子邮件发送,您应该定义一个toMail 通知类上的方法。这个方法会收到一个$notifiable 实体,应该返回一个Illuminate\Notifications\Messages\MailMessage 实例。

MailMessage 类包含一些简单的方法来帮助您构建事务性电子邮件消息。邮件消息可能包含文本行以及“号召性用语”。让我们看一个例子toMail 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    $url = url('/invoice/'.$this->invoice->id);

    return (new MailMessage)
                ->greeting('Hello!')
                ->line('One of your invoices has been paid!')
                ->lineIf($this->amount > 0, "Amount paid: {$this->amount}")
                ->action('View Invoice', $url)
                ->line('Thank you for using our application!');
}

Note
注意我们正在使用$this->invoice->id 在我们的toMail 方法。您可以将通知生成消息所需的任何数据传递到通知的构造函数中。

在此示例中,我们注册了一条问候语、一行文本、一个号召性用语,然后是另一行文本。这些方法由MailMessage 对象使格式化小型交易电子邮件变得简单快捷。然后,邮件通道会将消息组件转换为漂亮的响应式 HTML 电子邮件模板,并带有纯文本副本。这是由mail 渠道:

Note
发送邮件通知时,请务必设置name 你的配置选项config/app.php 配置文件。该值将用于邮件通知消息的页眉和页脚。

错误讯息

一些通知通知用户错误,例如发票支付失败。您可以通过调用error 构建消息时的方法。当使用error 邮件消息上的方法,号召性用语按钮将是红色而不是黑色:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->error()
                ->subject('Invoice Payment Failed')
                ->line('...');
}

其他邮件通知格式选项

您可以使用view 指定用于呈现通知电子邮件的自定义模板的方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)->view(
        'emails.name', ['invoice' => $this->invoice]
    );
}

您可以通过将视图名称作为给定的数组的第二个元素来为邮件消息指定纯文本视图view 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)->view(
        ['emails.name.html', 'emails.name.plain'],
        ['invoice' => $this->invoice]
    );
}

自定义发件人

默认情况下,电子邮件的发件人/发件人地址在config/mail.php 配置文件。但是,您可以使用from 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->from('barrett@example.com', 'Barrett Blair')
                ->line('...');
}

自定义收件人

当通过mail 频道,通知系统会自动寻找一个email 您的应通报实体的财产。您可以通过定义一个电子邮件地址来自定义用于发送通知的电子邮件地址routeNotificationForMail 应通报实体的方法:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * Route notifications for the mail channel.
     *
     * @return  array<string, string>|string
     */
    public function routeNotificationForMail(Notification $notification): array|string
    {
        // Return email address only...
        return $this->email_address;

        // Return email address and name...
        return [$this->email_address => $this->name];
    }
}

自定义主题

默认情况下,电子邮件的主题是格式为“Title Case”的通知的类名。所以,如果你的通知类被命名InvoicePaid, 电子邮件的主题将是Invoice Paid.如果您想为消息指定不同的主题,您可以调用subject 构建消息时的方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->subject('Notification Subject')
                ->line('...');
}

自定义邮件程序

默认情况下,电子邮件通知将使用在config/mail.php 配置文件。但是,您可以在运行时通过调用mailer 构建消息时的方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->mailer('postmark')
                ->line('...');
}

自定义模板

您可以通过发布通知包的资源来修改邮件通知使用的 HTML 和纯文本模板。运行此命令后,邮件通知模板将位于resources/views/vendor/notifications目录:

php artisan vendor:publish --tag=laravel-notifications

Attachments

要向电子邮件通知添加附件,请使用attach 构建消息时的方法。这attach 方法接受文件的绝对路径作为它的第一个参数:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->greeting('Hello!')
                ->attach('/path/to/file');
}

Note
attach 通知邮件消息提供的方法也接受可附着物.请咨询综合可附加对象文档 了解更多。

将文件附加到邮件时,您还可以通过传递array 作为第二个参数attach 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->greeting('Hello!')
                ->attach('/path/to/file', [
                    'as' => 'name.pdf',
                    'mime' => 'application/pdf',
                ]);
}

与在可邮寄对象中附加文件不同,您不能使用直接从存储磁盘附加文件attachFromStorage.你应该使用attach 使用存储磁盘上文件的绝对路径的方法。或者,您可以返回一个mailable 来自toMail 方法:

use App\Mail\InvoicePaid as InvoicePaidMailable;

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): Mailable
{
    return (new InvoicePaidMailable($this->invoice))
                ->to($notifiable->email)
                ->attachFromStorage('/path/to/file');
}

必要时,可以使用attachMany 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->greeting('Hello!')
                ->attachMany([
                    '/path/to/forge.svg',
                    '/path/to/vapor.svg' => [
                        'as' => 'Logo.svg',
                        'mime' => 'image/svg+xml',
                    ],
                ]);
}

原始数据附件

attachData 方法可用于附加字节的原始字符串作为附件。当调用attachData 方法,您应该提供应分配给附件的文件名:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->greeting('Hello!')
                ->attachData($this->pdf, 'name.pdf', [
                    'mime' => 'application/pdf',
                ]);
}

添加标签和元数据

某些第三方电子邮件提供商(例如 Mailgun 和 Postmark)支持消息“标签”和“元数据”,它们可用于对您的应用程序发送的电子邮件进行分组和跟踪。您可以通过以下方式将标签和元数据添加到电子邮件中tagmetadata 方法:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->greeting('Comment Upvoted!')
                ->tag('upvote')
                ->metadata('comment_id', $this->comment->id);
}

如果您的应用程序正在使用 Mailgun 驱动程序,您可以查阅 Mailgun 的文档以获取更多信息tagsmetadata.同样,还可以查阅 Postmark 文档以获取有关其支持的更多信息tagsmetadata.

如果您的应用程序使用 Amazon SES 发送电子邮件,您应该使用metadata 附加方法SES“标签” 到消息。

自定义 Symfony 消息

withSymfonyMessage 的方法MailMessage 类允许您注册一个闭包,在发送消息之前将使用 Symfony Message 实例调用该闭包。这使您有机会在消息传递之前对其进行深度定制:

use Symfony\Component\Mime\Email;

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->withSymfonyMessage(function (Email $message) {
                    $message->getHeaders()->addTextHeader(
                        'Custom-Header', 'Header Value'
                    );
                });
}

使用邮件

如果需要,您可以返回一个完整的可邮寄物品 从你的通知toMail 方法。当返回一个Mailable 代替MailMessage,您将需要使用可邮寄对象的to 方法:

use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Mail\Mailable;

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): Mailable
{
    return (new InvoicePaidMailable($this->invoice))
                ->to($notifiable->email);
}

邮件和按需通知

如果您要发送按需通知, 这$notifiable 给的实例toMail 方法将是一个实例Illuminate\Notifications\AnonymousNotifiable,它提供了一个routeNotificationFor 可用于检索应将按需通知发送到的电子邮件地址的方法:

use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Mail\Mailable;

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): Mailable
{
    $address = $notifiable instanceof AnonymousNotifiable
            ? $notifiable->routeNotificationFor('mail')
            : $notifiable->email;

    return (new InvoicePaidMailable($this->invoice))
                ->to($address);
}

预览邮件通知

在设计邮件通知模板时,可以像典型的 Blade 模板一样方便地在浏览器中快速预览呈现的邮件消息。出于这个原因,Laravel 允许您直接从路由闭包或控制器返回由邮件通知生成的任何邮件消息。当一个MailMessage 返回时,它将在浏览器中呈现和显示,使您可以快速预览其设计,而无需将其发送到实际的电子邮件地址:

use App\Models\Invoice;
use App\Notifications\InvoicePaid;

Route::get('/notification', function () {
    $invoice = Invoice::find(1);

    return (new InvoicePaid($invoice))
                ->toMail($invoice->user);
});

降价邮件通知

Markdown 邮件通知让您可以利用邮件通知的预建模板,同时让您更自由地编写更长的自定义消息。由于消息是用 Markdown 编写的,Laravel 能够为消息呈现漂亮的响应式 HTML 模板,同时还自动生成纯文本副本。

生成消息

要使用相应的 Markdown 模板生成通知,您可以使用--markdown 的选项make:notification 工匠命令:

php artisan make:notification InvoicePaid --markdown=mail.invoice.paid

与所有其他邮件通知一样,使用 Markdown 模板的通知应该定义一个toMail 他们的通知类上的方法。但是,而不是使用lineaction 构造通知的方法,使用markdown 方法来指定应该使用的 Markdown 模板的名称。您希望模板可用的数据数组可以作为方法的第二个参数传递:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    $url = url('/invoice/'.$this->invoice->id);

    return (new MailMessage)
                ->subject('Invoice Paid')
                ->markdown('mail.invoice.paid', ['url' => $url]);
}

写信息

Markdown 邮件通知使用 Blade 组件和 Markdown 语法的组合,允许您在利用 Laravel 的预制通知组件的同时轻松构建通知:

<x-mail::message>
# Invoice Paid

Your invoice has been paid!

<x-mail::button :url="$url">
View Invoice
</x-mail::button>

Thanks,<br>
{{ config('app.name') }}
</x-mail::message>

按钮组件

按钮组件呈现居中按钮链接。该组件接受两个参数,一个url 和一个可选的color.支持的颜色有primary,green, 和red.您可以根据需要向通知添加任意数量的按钮组件:

<x-mail::button :url="$url" color="green">
View Invoice
</x-mail::button>

面板组件

面板组件在面板中呈现给定的文本块,该面板的背景颜色与通知的其余部分略有不同。这使您可以将注意力吸引到给定的文本块:

<x-mail::panel>
This is the panel content.
</x-mail::panel>

表格组件

表格组件允许您将 Markdown 表格转换为 HTML 表格。该组件接受 Markdown 表格作为其内容。使用默认的 Markdown 表格对齐语法支持表格列对齐:

<x-mail::table>
| Laravel       | Table         | Example  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      | $10      |
| Col 3 is      | Right-Aligned | $20      |
</x-mail::table>

自定义组件

您可以将所有 Markdown 通知组件导出到您自己的应用程序中进行自定义。要导出组件,请使用vendor:publish Artisan 命令发布laravel-mail 资产标签:

php artisan vendor:publish --tag=laravel-mail

此命令会将 Markdown 邮件组件发布到resources/views/vendor/mail 目录。这mail 目录将包含一个html 和一个text 目录,每个目录包含每个可用组件的各自表示。您可以随意自定义这些组件。

自定义 CSS

导出组件后,resources/views/vendor/mail/html/themes 目录将包含一个default.css 文件。您可以在此文件中自定义 CSS,您的样式将自动内嵌在 Markdown 通知的 HTML 表示中。

如果你想为 Laravel 的 Markdown 组件构建一个全新的主题,你可以将一个 CSS 文件放在html/themes 目录。命名并保存 CSS 文件后,更新theme 的选项mail 配置文件以匹配新主题的名称。

要为单个通知自定义主题,您可以调用theme 构建通知邮件消息时的方法。这theme 方法接受发送通知时应使用的主题名称:

/**
 * Get the mail representation of the notification.
 */
public function toMail(object $notifiable): MailMessage
{
    return (new MailMessage)
                ->theme('invoice')
                ->subject('Invoice Paid')
                ->markdown('mail.invoice.paid', ['url' => $url]);
}

数据库通知

Prerequisites

database 通知通道将通知信息存储在数据库表中。该表将包含通知类型以及描述通知的 JSON 数据结构等信息。

您可以查询该表以在应用程序的用户界面中显示通知。但是,在此之前,您需要创建一个数据库表来保存您的通知。您可以使用notifications:table 命令生成一个migration 使用适当的表模式:

php artisan notifications:table

php artisan migrate

格式化数据库通知

如果一个通知支持存储在数据库表中,你应该定义一个toDatabase 或者toArray 通知类上的方法。这个方法会收到一个$notifiable entity 并且应该返回一个普通的 PHP 数组。返回的数组将被编码为 JSON 并存储在data 你的专栏notifications 桌子。让我们看一个例子toArray 方法:

/**
 * Get the array representation of the notification.
 *
 * @return array<string, mixed>
 */
public function toArray(object $notifiable): array
{
    return [
        'invoice_id' => $this->invoice->id,
        'amount' => $this->invoice->amount,
    ];
}

toDatabase 比。toArray

toArray 方法也被使用broadcast 通道来确定将哪些数据广播到您的 JavaScript 驱动的前端。如果你想有两个不同的数组表示databasebroadcast 渠道,你应该定义一个toDatabase 方法而不是toArray 方法。

访问通知

一旦通知存储在数据库中,您就需要一种方便的方式从您的可通知实体访问它们。这Illuminate\Notifications\Notifiable trait,包含在 Laravel 的默认设置中App\Models\User 模型,包括一个notifications 雄辩的关系 返回实体的通知。要获取通知,您可以像任何其他 Eloquent 关系一样访问此方法。默认情况下,通知将按created_at 收集开始时带有最新通知的时间戳:

$user = App\Models\User::find(1);

foreach ($user->notifications as $notification) {
    echo $notification->type;
}

如果你只想检索“未读”通知,你可以使用unreadNotifications 关系。同样,这些通知将按created_at 收集开始时带有最新通知的时间戳:

$user = App\Models\User::find(1);

foreach ($user->unreadNotifications as $notification) {
    echo $notification->type;
}

Note
要从您的 JavaScript 客户端访问您的通知,您应该为您的应用程序定义一个通知控制器,它返回通知实体的通知,例如当前用户。然后,您可以从 JavaScript 客户端向该控制器的 URL 发出 HTTP 请求。

将通知标记为已读

通常,您会希望在用户查看通知时将其标记为“已读”。这Illuminate\Notifications\Notifiable 特质提供了markAsRead 方法,更新read_at 通知数据库记录的列:

$user = App\Models\User::find(1);

foreach ($user->unreadNotifications as $notification) {
    $notification->markAsRead();
}

但是,您可以使用markAsRead 直接在通知集合上的方法:

$user->unreadNotifications->markAsRead();

您还可以使用批量更新查询将所有通知标记为已读,而无需从数据库中检索它们:

$user = App\Models\User::find(1);

$user->unreadNotifications()->update(['read_at' => now()]);

您可以delete 将它们从表中完全删除的通知:

$user->notifications()->delete();

广播通知

Prerequisites

在广播通知之前,你应该配置并熟悉 Laravel 的事件广播 服务。事件广播提供了一种从 JavaScript 驱动的前端对服务器端 Laravel 事件做出反应的方法。

格式化广播通知

broadcast 频道使用 Laravel 的广播通知事件广播 服务,允许您的 JavaScript 驱动的前端实时捕获通知。如果一个通知支持广播,你可以定义一个toBroadcast 通知类上的方法。这个方法会收到一个$notifiable 实体,应该返回一个BroadcastMessage 实例。如果toBroadcast 方法不存在,则toArray 方法将用于收集应该广播的数据。返回的数据将被编码为 JSON 并广播到您的 JavaScript 驱动的前端。让我们看一个例子toBroadcast 方法:

use Illuminate\Notifications\Messages\BroadcastMessage;

/**
 * Get the broadcastable representation of the notification.
 */
public function toBroadcast(object $notifiable): BroadcastMessage
{
    return new BroadcastMessage([
        'invoice_id' => $this->invoice->id,
        'amount' => $this->invoice->amount,
    ]);
}

广播队列配置

所有广播通知都排队等待广播。如果您想配置用于排队广播操作的队列连接或队列名称,您可以使用onConnectiononQueue 的方法BroadcastMessage:

return (new BroadcastMessage($data))
                ->onConnection('sqs')
                ->onQueue('broadcasts');

自定义通知类型

除了你指定的数据,所有的广播通知还有一个type 包含通知的完整类名的字段。如果您想自定义通知type,你可以定义一个broadcastType 通知类的方法:

/**
 * Get the type of the notification being broadcast.
 */
public function broadcastType(): string
{
    return 'broadcast.message';
}

监听通知

通知将在使用格式的私人频道上广播{notifiable}.{id} 习俗。因此,如果您要将通知发送到App\Models\User ID 为的实例1, 通知将在App.Models.User.1 私人频道。使用时Laravel 回声,您可以使用notification 方法:

Echo.private('App.Models.User.' + userId)
    .notification((notification) => {
        console.log(notification.type);
    });

自定义通知通道

如果您想自定义广播实体广播通知的频道,您可以定义一个receivesBroadcastNotificationsOn 应通报实体的方法:

<?php

namespace App\Models;

use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The channels the user receives notification broadcasts on.
     */
    public function receivesBroadcastNotificationsOn(): string
    {
        return 'users.'.$this->id;
    }
}

短信通知

Prerequisites

在 Laravel 中发送短信通知由Vonage (以前称为 Nexmo)。在您可以通过 Vonage 发送通知之前,您需要安装laravel/vonage-notification-channelguzzlehttp/guzzle 包裹:

composer require laravel/vonage-notification-channel guzzlehttp/guzzle

该包包括一个配置文件.但是,您不需要将此配置文件导出到您自己的应用程序中。您可以简单地使用VONAGE_KEYVONAGE_SECRET 环境变量来定义您的 Vonage 公钥和私钥。

定义密钥后,您应该设置一个VONAGE_SMS_FROM 环境变量,用于定义默认情况下应发送 SMS 消息的电话号码。您可以在 Vonage 控制面板中生成此电话号码:

VONAGE_SMS_FROM=15556666666

格式化短信通知

如果通知支持作为 SMS 发送,您应该定义一个toVonage 通知类上的方法。这个方法会收到一个$notifiable 实体,应该返回一个Illuminate\Notifications\Messages\VonageMessage 实例:

use Illuminate\Notifications\Messages\VonageMessage;

/**
 * Get the Vonage / SMS representation of the notification.
 */
public function toVonage(object $notifiable): VonageMessage
{
    return (new VonageMessage)
                ->content('Your SMS message content');
}

Unicode 内容

如果您的 SMS 消息将包含 unicode 字符,您应该调用unicode 构建时的方法VonageMessage 实例:

use Illuminate\Notifications\Messages\VonageMessage;

/**
 * Get the Vonage / SMS representation of the notification.
 */
public function toVonage(object $notifiable): VonageMessage
{
    return (new VonageMessage)
                ->content('Your unicode message')
                ->unicode();
}

自定义“发件人”号码

如果您想从与您指定的电话号码不同的电话号码发送一些通知VONAGE_SMS_FROM 环境变量,你可以调用from 上的方法VonageMessage 实例:

use Illuminate\Notifications\Messages\VonageMessage;

/**
 * Get the Vonage / SMS representation of the notification.
 */
public function toVonage(object $notifiable): VonageMessage
{
    return (new VonageMessage)
                ->content('Your SMS message content')
                ->from('15554443333');
}

添加客户参考

如果您想跟踪每个用户、团队或客户的成本,您可以在通知中添加“客户参考”。 Vonage 将允许您使用此客户端参考生成报告,以便您可以更好地了解特定客户的 SMS 使用情况。客户端参考可以是最多 40 个字符的任何字符串:

use Illuminate\Notifications\Messages\VonageMessage;

/**
 * Get the Vonage / SMS representation of the notification.
 */
public function toVonage(object $notifiable): VonageMessage
{
    return (new VonageMessage)
                ->clientReference((string) $notifiable->id)
                ->content('Your SMS message content');
}

路由短信通知

要将 Vonage 通知路由到正确的电话号码,请定义一个routeNotificationForVonage 应通知实体的方法:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * Route notifications for the Vonage channel.
     */
    public function routeNotificationForVonage(Notification $notification): string
    {
        return $this->phone_number;
    }
}

松弛通知

Prerequisites

在您可以通过 Slack 发送通知之前,您必须通过 Composer 安装 Slack 通知通道:

composer require laravel/slack-notification-channel

您还需要创建一个松弛应用程序 为您的团队。创建应用程序后,您应该为工作区配置一个“Incoming Webhook”。 Slack 然后会为您提供一个 webhook URL,您可以在路由松弛通知.

格式化 Slack 通知

如果通知支持作为 Slack 消息发送,您应该定义一个toSlack 通知类上的方法。这个方法会收到一个$notifiable 实体,应该返回一个Illuminate\Notifications\Messages\SlackMessage 实例。 Slack 消息可能包含文本内容以及格式化附加文本或字段数组的“附件”。让我们来看看一个基本的toSlack 例子:

use Illuminate\Notifications\Messages\SlackMessage;

/**
 * Get the Slack representation of the notification.
 */
public function toSlack(object $notifiable): SlackMessage
{
    return (new SlackMessage)
                ->content('One of your invoices has been paid!');
}

松弛附件

您还可以向 Slack 消息添加“附件”。附件提供比简单文本消息更丰富的格式设置选项。在此示例中,我们将发送有关应用程序中发生的异常的错误通知,包括用于查看有关异常的更多详细信息的链接:

use Illuminate\Notifications\Messages\SlackAttachment;
use Illuminate\Notifications\Messages\SlackMessage;

/**
 * Get the Slack representation of the notification.
 */
public function toSlack(object $notifiable): SlackMessage
{
    $url = url('/exceptions/'.$this->exception->id);

    return (new SlackMessage)
                ->error()
                ->content('Whoops! Something went wrong.')
                ->attachment(function (SlackAttachment $attachment) use ($url) {
                    $attachment->title('Exception: File Not Found', $url)
                               ->content('File [background.jpg] was not found.');
                });
}

附件还允许您指定应呈现给用户的数据数组。给定的数据将以表格形式呈现,以便于阅读:

use Illuminate\Notifications\Messages\SlackAttachment;
use Illuminate\Notifications\Messages\SlackMessage;

/**
 * Get the Slack representation of the notification.
 */
public function toSlack(object $notifiable): SlackMessage
{
    $url = url('/invoices/'.$this->invoice->id);

    return (new SlackMessage)
                ->success()
                ->content('One of your invoices has been paid!')
                ->attachment(function (SlackAttachment $attachment) use ($url) {
                    $attachment->title('Invoice 1322', $url)
                               ->fields([
                                    'Title' => 'Server Expenses',
                                    'Amount' => '$1,234',
                                    'Via' => 'American Express',
                                    'Was Overdue' => ':-1:',
                                ]);
                });
}

Markdown 附件内容

如果您的某些附件字段包含 Markdown,您可以使用markdown 指示 Slack 解析给定附件字段并将其显示为 Markdown 格式文本的方法。此方法接受的值为:pretext,text, 和/或fields.有关 Slack 附件格式的更多信息,请查看松弛 API 文档:

use Illuminate\Notifications\Messages\SlackAttachment;
use Illuminate\Notifications\Messages\SlackMessage;

/**
 * Get the Slack representation of the notification.
 */
public function toSlack(object $notifiable): SlackMessage
{
    $url = url('/exceptions/'.$this->exception->id);

    return (new SlackMessage)
                ->error()
                ->content('Whoops! Something went wrong.')
                ->attachment(function (SlackAttachment $attachment) use ($url) {
                    $attachment->title('Exception: File Not Found', $url)
                               ->content('File [background.jpg] was *not found*.')
                               ->markdown(['text']);
                });
}

路由松弛通知

要将 Slack 通知路由到适当的 Slack 团队和频道,请定义一个routeNotificationForSlack 应通知实体的方法。这应该返回通知应该传送到的 webhook URL。可以通过向您的 Slack 团队添加“Incoming Webhook”服务来生成 Webhook URL:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * Route notifications for the Slack channel.
     */
    public function routeNotificationForSlack(Notification $notification): string
    {
        return 'https://hooks.slack.com/services/...';
    }
}

本地化通知

Laravel 允许您在不同于 HTTP 请求的当前区域设置的区域设置中发送通知,并且如果通知排队,甚至会记住该区域设置。

为了实现这一目标,Illuminate\Notifications\Notification 班级提供locale 方法来设置所需的语言。评估通知时,应用程序将更改为该语言环境,然后在评估完成后恢复为之前的语言环境:

$user->notify((new InvoicePaid($invoice))->locale('es'));

多个须通报条目的本地化也可以通过Notification 正面:

Notification::locale('es')->send(
    $users, new InvoicePaid($invoice)
);

用户首选语言环境

有时,应用程序会存储每个用户的首选语言环境。通过实施HasLocalePreference 在你的可通知模型上契约,你可以指示 Laravel 在发送通知时使用这个存储的语言环境:

use Illuminate\Contracts\Translation\HasLocalePreference;

class User extends Model implements HasLocalePreference
{
    /**
     * Get the user's preferred locale.
     */
    public function preferredLocale(): string
    {
        return $this->locale;
    }
}

一旦你实现了接口,Laravel 将在向模型发送通知和邮件时自动使用首选语言环境。因此,无需调用locale 使用该接口时的方法:

$user->notify(new InvoicePaid($invoice));

Testing

您可以使用Notification 门面的fake 防止发送通知的方法。通常,发送通知与您实际测试的代码无关。最有可能的是,简单地断言 Laravel 被指示发送给定通知就足够了。

调用后Notification 门面的fake 方法,然后你可以断言通知被指示发送给用户,甚至检查通知收到的数据:

<?php

namespace Tests\Feature;

use App\Notifications\OrderShipped;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_orders_can_be_shipped(): void
    {
        Notification::fake();

        // Perform order shipping...

        // Assert that no notifications were sent...
        Notification::assertNothingSent();

        // Assert a notification was sent to the given users...
        Notification::assertSentTo(
            [$user], OrderShipped::class
        );

        // Assert a notification was not sent...
        Notification::assertNotSentTo(
            [$user], AnotherNotification::class
        );

        // Assert that a given number of notifications were sent...
        Notification::assertCount(3);
    }
}

您可以将闭包传递给assertSentTo 或者assertNotSentTo 方法来断言已发送通过给定“真实性测试”的通知。如果至少发送了一个通过给定真值测试的通知,则断言将成功:

Notification::assertSentTo(
    $user,
    function (OrderShipped $notification, array $channels) use ($order) {
        return $notification->order->id === $order->id;
    }
);

按需通知

如果您正在测试的代码发送按需通知,您可以测试点播通知是通过assertSentOnDemand 方法:

Notification::assertSentOnDemand(OrderShipped::class);

通过将闭包作为第二个参数传递给assertSentOnDemand 方法,您可以确定是否将按需通知发送到正确的“路由”地址:

Notification::assertSentOnDemand(
    OrderShipped::class,
    function (OrderShipped $notification, array $channels, object $notifiable) use ($user) {
        return $notifiable->routes['mail'] === $user->email;
    }
);

通知事件

通知发送事件

发送通知时,Illuminate\Notifications\Events\NotificationSending event 由通知系统调度。这包含“可通知”实体和通知实例本身。您可以在您的应用程序的EventServiceProvider:

use App\Listeners\CheckNotificationStatus;
use Illuminate\Notifications\Events\NotificationSending;

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    NotificationSending::class => [
        CheckNotificationStatus::class,
    ],
];

如果事件监听器将不会发送通知NotificationSending 事件回报false 从它的handle 方法:

use Illuminate\Notifications\Events\NotificationSending;

/**
 * Handle the event.
 */
public function handle(NotificationSending $event): void
{
    return false;
}

在事件侦听器中,您可以访问notifiable,notification, 和channel 事件的属性以了解有关通知收件人或通知本身的更多信息:

/**
 * Handle the event.
 */
public function handle(NotificationSending $event): void
{
    // $event->channel
    // $event->notifiable
    // $event->notification
}

通知发送事件

发送通知时,Illuminate\Notifications\Events\NotificationSent event 由通知系统调度。这包含“可通知”实体和通知实例本身。您可以在您的EventServiceProvider:

use App\Listeners\LogNotification;
use Illuminate\Notifications\Events\NotificationSent;

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    NotificationSent::class => [
        LogNotification::class,
    ],
];

Note
在你的注册听众之后EventServiceProvider, 使用event:generate 用于快速生成侦听器类的 Artisan 命令。

在事件侦听器中,您可以访问notifiable,notification,channel, 和response 事件的属性以了解有关通知收件人或通知本身的更多信息:

/**
 * Handle the event.
 */
public function handle(NotificationSent $event): void
{
    // $event->channel
    // $event->notifiable
    // $event->notification
    // $event->response
}

自定义频道

Laravel 附带了一些通知渠道,但您可能希望编写自己的驱动程序以通过其他渠道发送通知。 Laravel 使它变得简单。首先,定义一个类,其中包含send 方法。该方法应接收两个参数:$notifiable 和一个$notification.

send 方法,您可以调用通知上的方法来检索您的频道理解的消息对象,然后将通知发送到$notifiable 实例但是你想要:

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;

class VoiceChannel
{
    /**
     * Send the given notification.
     */
    public function send(object $notifiable, Notification $notification): void
    {
        $message = $notification->toVoice($notifiable);

        // Send notification to the $notifiable instance...
    }
}

定义通知通道类后,您可以从via 您的任何通知的方法。在这个例子中,toVoice 通知的方法可以返回您选择代表语音消息的任何对象。例如,您可以定义自己的VoiceMessage 类来表示这些消息:

<?php

namespace App\Notifications;

use App\Notifications\Messages\VoiceMessage;
use App\Notifications\VoiceChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;

class InvoicePaid extends Notification
{
    use Queueable;

    /**
     * Get the notification channels.
     */
    public function via(object $notifiable): string
    {
        return VoiceChannel::class;
    }

    /**
     * Get the voice representation of the notification.
     */
    public function toVoice(object $notifiable): VoiceMessage
    {
        // ...
    }
}
豫ICP备18041297号-2