Using multiple channels to send notifications in Laravel


brief introduction

In addition to support Send Mail In addition, Larave also supports sending notifications through multiple transmission channels, including email, SMS (via Nexmo )And Slack Etc. Notifications can be stored in the database for later display in the Web interface.

Usually, notifications are short messages used to inform users of events occurring in the application. For example, if you are developing a billing application, you need to send a "bill payment" notification to users through email or SMS.

Create Notification

In Laravel, each notification exists as a separate class (usually stored in app/Notifications Directory), if you don't see this directory in the application, don't worry, it will run the Artisan command make:notification Automatically create:

 php artisan make:notification InvoicePaid

The command will app/Notifications Generate a new notification class under the directory. Each notification class contains a via Methods and multiple message building methods (such as toMail or toDatabase )These message building methods are used to transform notifications into messages optimized by specific channels. The template code generated by default is as follows:

 <? php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; class InvoicePaid extends Notification { use Queueable; /** * Create a new notification instance. * * @return void */ public function __construct() { // } /** * 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 (new MailMessage) ->line('The introduction to the notification.') ->action('Notification Action', url('/')) ->line('Thank you for using our application!'); } /** * Get the array representation of the notification. * * @param  mixed  $notifiable * @return array */ public function toArray($notifiable) { return [ // ]; } }

Send notification

Using the Notifiable Train

Notifications can be sent in two ways: using Notifiable Provided by trait notify Method or use Notification Facade First, we use Notifiable Trait to test:

 <? php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; }

This trait is defaulted to App\User The model uses and provides a method for sending notifications: notify notify Method receives a notification instance:

 use App\Notifications\InvoicePaid; $user->notify(new InvoicePaid($invoice));
Note: You can use it in any model Illuminate\Notifications\Notifiable Trait, not limited to User Used in the model.

Use Notification Facade

As an alternative, you can also use Notification Facade Send notifications. This is useful when you need to send notifications to multiple users. To use this facade to send notifications, you need to send all notified users and notification instances to send method:

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

Specify transmission channel

Each notification class has one via Method is used to determine which channel the notification is transmitted through, and Laravel supports unpacking mail database broadcast nexmo as well as slack Channel.

Note: If you want to use other transmission channels, such as Telegram or Pusher, refer to the drivers provided by the community: Larravel Notification Channel Website

via Method receives a $notifiable Instance, used to specify the class instance to which the notification is sent. You can use $notifiable To determine the channel through which notifications are transmitted:

 /** *Get the delivery channel of the notice * * @param  mixed  $notifiable * @return array * @translator laravelacademy.org */ public function via($notifiable) { return $notifiable->prefers_sms ?  ['nexmo'] : ['mail', 'database']; }

Notification Queue

Note: Before using the notification queue, you need to configure the queue and Open a queue task

Sending notifications can be time-consuming, especially if the channel needs to call additional APIs to transmit notifications. In order to speed up the response time of the application, the notification can be pushed to the queue and sent asynchronously. To push the notification to the queue, the corresponding notification class can ShouldQueue Interface and use Queueable trait。 If the notification class is passed through make:notification The interface and trait have been imported by default. You can quickly add them to the notification class:

 <? php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification implements ShouldQueue { use Queueable; // ... }

ShouldQueue After the interface is added to the notification class, you can send notifications as before, and Larvel will automatically detect ShouldQueue The interface then pushes the notification to the queue:

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

If you want to delay the sending of notifications, you can add delay method:

 $when = Carbon::now()->addMinutes(10); $user->notify((new InvoicePaid($invoice))->delay($when));

On demand notification

Sometimes you may need to send a notification to a user, but the user does not exist in the application user system. To achieve this goal, we use Notification::route Method specifies a special notification route before sending:

 Notification::route('mail', ' taylor@laravel.com ') ->route('nexmo', '5555555555') ->notify(new InvoicePaid($invoice));

Email notification

Format Mail Message

If the notification supports sending by email, you need to define a toMail method. This method will receive a $notifiable Entity and return Illuminate\Notifications\Messages\MailMessage example. Mail messages can contain multiple lines of text and call actions. Let's take a look at toMail Examples of methods:

 /** *Get the email corresponding to the notification * * @param  mixed  $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->greeting('Hello!') ->line('One of your invoices has been paid!') ->action('View Invoice', $url) ->line('Thank you for using our application!'); }
Note: Note that we have message Method $this->invoice->id , you can pass any data required by the notification generation message to the notification constructor.

In this example, we registered a greeting, a line of text, a call to an action, and another line of text. MailMessage Object makes it easy and fast to format short transaction messages. mail The channel will transform the message component into a beautiful, responsive HTML mail template with a plain text copy. The following is an example mail Examples of messages generated by channels:

 notification-example

Note: When sending email notifications, ensure that the configuration file config/app.php Is set in name The value of, which will be used in the header and footer of the mail notification message.

Other notification formatting options

In addition to defining multiline text in the notification class, you can also use view Method to specify a custom template for rendering notification messages:

 /** *Get notification email * * @param  mixed  $notifiable * @return \Illuminate\Notifications\Messages\MailMessage * @translator laravelacademy.org */ public function toMail($notifiable) { return (new MailMessage)->view( 'emails.name', ['invoice' => $this->invoice] ); }

In addition, you can choose from toMail Method returns a Mailable objects

 use App\Mail\InvoicePaid as Mailable; /** *Get notification email * * @param  mixed  $notifiable * @return Mailable */ public function toMail($notifiable) { return new Mailable($this->invoice)->to($this->user->email); }

Error message

Some notifications will inform users of error information, such as failed order payment. You can call the error Method to indicate that the mail message represents an error message. Use in mail messages error Method, the action button will turn red:

 /** *Get notification email * * @param  mixed  $notifiable * @return \Illuminate\Notifications\Message */ public function toMail($notifiable) { return (new MailMessage) ->error() ->subject('Notification Subject') ->line('...'); }

Custom recipient

adopt mail When the channel sends a notification, the notification system will automatically search the notified entity email Attribute, you can define a routeNotificationForMail Customize which email address is used to send notifications:

 <? php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the mail channel. * * @return string */ public function routeNotificationForMail() { return $this->email_address; } }

Custom Theme

By default, the subject of the email is the notification class name in the format of "title style". Therefore, if the notification class is named as InvoicePaid The subject of the email is Invoice Paid If you want to specify a specific subject for the message, you can call subject method:

 /** * Get the mail representation of the notification. * * @param  mixed  $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->subject('Notification Subject') ->line('...'); }

Custom Template

You can modify the HTML and plain text templates used for email notifications by publishing the resources of the notification expansion package. After running the following command, the email notification template will be stored in resources/views/vendor/notifications catalog:

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

Markdown email notification

Markdown email notification allows you to use the preset template of email notification, so that you can freely write longer and more personalized messages. Because these messages are written in Markdown format, Laravel can also render high color, responsive HTML templates for them, and automatically generate plain text copies.

Generate Message

To generate a notification with a corresponding Markdown template, you can use the Artisan command make:notification Time band --markdown Options:

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

Like other mail notifications, the notification class using the Markdown template also needs to define a toMail method. However, you can use markdown Method replaces the line and action Method to specify the name of the Markdown template to use:

 /** * Get the mail representation of the notification. * * @param  mixed  $notifiable * @return \Illuminate\Notifications\Messages\MailMessage * @translator laravelacademy.org */ public function toMail($notifiable) { $url = url('/invoice/'.$this->invoice->id); return (new MailMessage) ->subject('Invoice Paid') ->markdown('mail.invoice.paid', ['url' => $url]); }

Write Message

Markdown email notifications use the Blade component and Markdown syntax together, so that you can easily build notifications without leaving the Laravel preset components:

 @component('mail::message') # Invoice Paid Your invoice has been paid! @component('mail::button', ['url' => $url]) View Invoice @endcomponent Thanks,<br> {{ config('app.name') }} @endcomponent

Button components

The button component renders a centered button link. This component receives two parameters, url And optional color , supported colors are blude green and red You can add any number of button components to the message:

 @component('mail::button', ['url' => $url, 'color' => 'green']) View Invoice @endcomponent

PANEL AS

The panel component renders the given text block into a panel with a faint background color to distinguish it from the surrounding messages. For text blocks requiring attention:

 @component('mail::panel') This is the panel content. @endcomponent

Table Components

The table component allows you to convert a Markdown table into an HTML table. This component receives the Markdown table as its content. Table column alignment supports the use of the default Markdown table column alignment syntax:

 @component('mail::table') | Laravel       | Table         | Example  | | ------------- |:-------------:| --------:| | Col 2 is      | Centered      | $10      | | Col 3 is      | Right-Aligned | $20      | @endcomponent

Custom Components

You can export all Markdown notification components to the application for customization. To export components, use the Artisan command vendor:publish To publish laravel-mail Resource tag:

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

This command will issue a Markdown email to notify the component to resources/views/vendor/mail catalog. mail Directory contains html and markdown Directory, and each subdirectory contains all its own valid components. You can edit these components as you like.

Custom CSS

After exporting components, resources/views/vendor/mail/html/themes The directory will contain a default default.css File, you can customize CSS in this file, so that the HTML style of Markdown notification will be automatically adjusted.

If you want to build a new theme for Markdown components, just click html/themes Write a new CSS file in the directory and modify it mail Profile's theme Option.

Database notification

Preparatory knowledge

database The notification channel stores notification information in the data table, which contains information such as notification type and custom JSON data used to describe notifications.

You can query this data table in the user interface to display notifications. However, before this, you need to create a data table to save information. You can use notifications:table Command to generate the migration file and then generate the corresponding data table:

 php artisan notifications:table php artisan migrate

Format Database Notification

If a notification supports being stored in a data table, it needs to be defined in the notification class toDatabase or toArray Method, which receives a $notifiable Entity and return a native PHP array. The returned array will be encoded in JSON format and stored in notifications Of table data Field. Let's take a look toArray Examples of methods:

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

toDatabase Vs. toArray

toArray The method is also broadcast The channel is used to determine what data to broadcast to the JavaScript client. If you want to database and broadcast If the channel provides two different array representations, you need to define one toDatabase Method to replace toArray method.

Access notifications

After notifications are stored in the data table, there needs to be a convenient way to access them in the notified entity. Larravel's default App\User Model introduced Illuminate\Notifications\Notifiable The trait contains the Eloquent association method that returns the corresponding notification of the entity notifications , to get these notifications, you can access this association method just as you access other Eloquent associations. By default, notifications are created_at Timestamp sorting:

 $user = App\User::find(1); foreach ($user->notifications as $notification) { echo $notification->type; }

If you only want to get "unread" notification, you can use association unreadNotifications Similarly, these notices are also created_at Timestamp sorting:

 $user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { echo $notification->type; }
Note: To access notifications from the JavaScript client, you need to define a notification controller in the application to return notifications for the specified notified entity (such as the current user), and then send an HTTP request from the JavaScript client to the corresponding URI of the controller.

Mark notification as read

Generally, we mark the notifications that users have browsed as read, Illuminate\Notifications\Notifiable Trait provides a markAsRead Method, used to update the read_at Field:

 $user = App\User::find(1); foreach ($user->unreadNotifications as $notification) { $notification->markAsRead(); }

If it is too troublesome to loop through each notification, you can call it directly on the notification collection markAsRead method:

 $user->unreadNotifications->markAsRead();

You can also mark the notification as read in batch update mode without first obtaining the notification from the database:

 $user = App\User::find(1); $user->unreadNotifications()->update(['read_at' => now()]);

Of course, you can also pass delete Method to remove these notifications from the database:

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

Broadcast notification

Preparatory knowledge

Before broadcast notification, you need to configure and understand Event broadcast Service, event broadcasting paves the way for JavaScript clients to respond to events triggered by the server.

Format broadcast notification

broadcast The channel broadcast notification uses Larave's Event broadcast Service, which allows JavaScript clients to capture notifications in real time. If the notification supports broadcasting, it needs to be defined on the notification class toBroadcast Method, which receives a $notifiable Entity and return a BroadcastMessage Instance, the returned array will be encoded into JSON format and then broadcast to the JavaScript client. Let's take a look toBroadcast Examples of methods:

 use Illuminate\Notifications\Messages\BroadcastMessage; /** * Get the broadcastable representation of the notification. * * @param  mixed  $notifiable * @return BroadcastMessage */ public function toBroadcast($notifiable) { return new BroadcastMessage([ 'invoice_id' => $this->invoice->id, 'amount' => $this->invoice->amount, ]); }

Broadcast Queue Configuration

All broadcast notifications will be pushed to the broadcast queue. If you want to configure the connection or name of the broadcast operation queue, you can use BroadcastMessage Of onConnection and onQueue method:

 return new BroadcastMessage($data) ->onConnection('sqs') ->onQueue('broadcasts');
In addition to the specified data, the broadcast notification also contains a type Field for the class name containing the notification.

Monitor notification

The notification will be formatted as {notifiable}. {id} Is broadcast on private channels, so if you want to send a notification to one Of App\User Instance, the notification will be on the private channel App. User.1 Broadcast on, if used Laravel Echo , you can use auxiliary functions notification Easily listen for notifications on a channel:

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

Custom notification channel

If you want to customize the notified entity to receive broadcast notifications on that channel, you can define a receivesBroadcastNotificationsOn method:

 <? php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** *The channel for users to receive broadcast notifications * * @return array */ public function receivesBroadcastNotificationsOn() { return 'users.'.$ this->id; } }

SMS notification

Preparatory knowledge

Larave is based on Nexmo Send SMS notifications. Before using Nexmo to send notifications, you need to install the corresponding Composer dependency package nexmo/client And in the configuration file config/services.php Configure accordingly in. You can start by copying the following sample configurations:

 'nexmo' => [ 'key' => env('NEXMO_KEY'), 'secret' => env('NEXMO_SECRET'), 'sms_from' => '15556666666', ],

sms_from The configuration item is the mobile phone number you use to send SMS messages. You need to generate a mobile phone number for the application in the Nexmo control panel.

Format SMS notification

If the notification supports sending by SMS, you need to define a toNexmo method. This method receives a $notifiable Entity and return Illuminate\Notifications\Messages\NexmoMessage example:

 /** * Get the Nexmo / SMS representation of the notification. * * @param  mixed  $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your SMS message content'); }

Unicode content

If your SMS message contains Unicode characters, you need to construct NexmoMessage Called on instance unicode method:

 /** * Get the Nexmo / SMS representation of the notification. * * @param  mixed  $notifiable * @return NexmoMessage */ public function toNexmo($notifiable) { return (new NexmoMessage) ->content('Your unicode message') ->unicode(); }

Custom Source Number

If you want to pass the config/services.php Other numbers with different mobile numbers specified in can be used to send notifications NexmoMessage On instance from Method:

 /**
 * Get the Nexmo / SMS representation of the notification.
 *
 * @param  mixed  $notifiable
 * @return NexmoMessage
 */
public function toNexmo($notifiable)
{
    return (new NexmoMessage)
        ->content('Your SMS message content')
        ->from('15554443333');
}

SMS notification routing

use nexmo When the channel sends a notification, the notification system will automatically search the notified entity phone_number Property. If you want to customize the mobile phone number to which the notification is sent, you can define a routeNotificationForNexmo method:

 <? php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Nexmo channel. * * @return string */ public function routeNotificationForNexmo() { return $this->phone; } }

Slack notification

Preparatory knowledge

Before sending notifications through Slack, you must install the Guzzle HTTP library through Composer (ignored if installed):

 composer require guzzlehttp/guzzle

In addition, you need to configure a“ Incoming Webhook ”Integration. The integration will be carried out in you Slack notification routing Provide a URL.

Format Slack Notification

If the notification supports sending through Slack messages, you need to define a toSlack Method, which receives a $notifiable Entity and return Illuminate\Notifications\Messages\SlackMessage Instance that contains text content and "attachments" that format additional text or array fields. Let's look at a basic toSlack Example of use:

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

In this example, we only send a simple line of text to Slack, and the final message created is as follows:

 basic-slack-notification Custom sender&receiver

You can use from and to Method defines the sender and receiver, from Method receives a user name and emoji ID, and to Method receiving channel or user name:

 /** * Get the Slack representation of the notification. * * @param  mixed  $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Ghost', ':ghost:') ->to('#other') ->content('This will be sent to #other'); }

You can also use images as logos to replace emoji:

 /** * Get the Slack representation of the notification. * * @param  mixed  $notifiable * @return SlackMessage */ public function toSlack($notifiable) { return (new SlackMessage) ->from('Laravel') ->image(' https://laravel.com/favicon.png ') ->content('This will display the Laravel logo next to the message'); }

Slack Accessories

You can also add "attachments" to Slack messages. Compared with simple text messages, attachments can provide more rich format options. In this example, we will send an exception error notification in the application, including a link to view more exception details:

 /** * Get the Slack representation of the notification. * * @param  mixed  $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was not found.'); }); }

The above code will generate the following Slack message:

 basic-slack-attachment

The attachment also allows you to specify the array data to be presented to the user. To improve readability, the given array will be displayed in table form:

 /** * Get the Slack representation of the notification. * * @param  mixed  $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/invoices/'.$this->invoice->id); return (new SlackMessage) ->success() ->content('One of your invoices has been paid!') ->attachment(function ($attachment) use ($url) { $attachment->title('Invoice 1322', $url) ->fields([ 'Title' => 'Server Expenses', 'Amount' => '$1,234', 'Via' => 'American Express', 'Was Overdue' => ':-1:', ]); }); }

The above code will generate the following Slack message:

 slack-fields-attachment Markdown attachment content

If some attachment fields contain Markdown, you can use markdown Method to build Slack to parse and display attachment fields written in Markdown format. The values supported by this method include pretext text ,/or fields To learn more about Slack formatting, see Slack API documentation

 /** * Get the Slack representation of the notification. * * @param  mixed  $notifiable * @return SlackMessage */ public function toSlack($notifiable) { $url = url('/exceptions/'.$this->exception->id); return (new SlackMessage) ->error() ->content('Whoops! Something went wrong.') ->attachment(function ($attachment) use ($url) { $attachment->title('Exception: File Not Found', $url) ->content('File [background.jpg] was *not found*.') ->markdown(['text']); }); }

Slack notification routing

To route the Slack notification to an appropriate location, you need to define a routeNotificationForSlack Method, which returns the Webhook URL to which the notification was sent. Webhook URL can be generated by adding an "Incoming Webhook" service to the Slack group:

 <? php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * Route notifications for the Slack channel. * * @return string */ public function routeNotificationForSlack() { return $this->slack_webhook_url; } }

Notify Events

When the notification is sent, the notification system will trigger Illuminate\Notifications\Events\NotificationSent Event, which contains the notified entity (such as user) and the notification instance itself. You can EventServiceProvider Register listeners for this event in:

 /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'Illuminate\Notifications\Events\NotificationSent' => [ 'App\Listeners\LogNotification', ], ];
Note: On EventServiceProvider After registering the listener in, use the Artisan command event:generate Quickly generate listener classes.

In the event listener, you can access the notifiable notification and channel Property for more information about the notification receiver and the notification itself:

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

Custom Channel

From the above introduction, we can see that Larravel provides us with a variety of notification channels, but if you want to write your own driver to send notifications through other channels, it is also very simple. First define a containing send Method, which receives two parameters: $notifiable and $notification

 <? php namespace App\Channels; use Illuminate\Notifications\Notification; class VoiceChannel { /** *Send the given notification * * @param  mixed  $notifiable * @param  \Illuminate\Notifications\Notification  $notification * @return void */ public function send($notifiable, Notification $notification) { $message = $notification->toVoice($notifiable); //Send notification to $notifiable instance } }

After the notification channel class is defined, you can use the via Method return class name:

 <? php namespace App\Notifications; use Illuminate\Bus\Queueable; use App\Channels\VoiceChannel; use App\Channels\Messages\VoiceMessage; use Illuminate\Notifications\Notification; use Illuminate\Contracts\Queue\ShouldQueue; class InvoicePaid extends Notification { use Queueable; /** *Get notification channel * * @param  mixed  $notifiable * @return array|string */ public function via($notifiable) { return [VoiceChannel::class]; } /** * Get the voice representation of the notification. * * @param  mixed  $notifiable * @return VoiceMessage */ public function toVoice($notifiable) { // ... } }

give the thumbs-up Cancel Like Collection Cancel Collection

<<Previous: Implement mail configuration, preview and sending in Larravel

>>Next: Development and use of Laravel custom expansion package