Introduction
In addition to support for sending email, Laravel provides support for sending notifications across a variety of delivery channels, including email, SMS (via Vonage, formerly known as Nexmo), and Slack. In addition, a variety of community built notification channels have been created to send notification over dozens of different channels! Notifications may also be stored in a database so they may be displayed in your web interface.
Typically, notifications should be short, informational messages that notify users of something that occurred in your application. For example, if you are writing a billing application, you might send an "Invoice Paid" notification to your users via the email and SMS channels.
Generating Notifications
In Laravel, each notification is represented by a single class that
is typically stored in the app/Notifications
directory.
Don't worry if you don't see this directory in your application - it
will be created for you when you run the make:notification
Artisan command:
php artisan make:notification InvoicePaid
This command will place a fresh notification class in your
app/Notifications
directory. Each notification class
contains a via
method and a variable number of message
building methods, such as toMail
or
toDatabase
, that convert the notification to a message
tailored for that particular channel.
Sending Notifications
Using The Notifiable Trait
Notifications may be sent in two ways: using the notify
method of the Notifiable
trait or using the
Notification
facade. The
Notifiable
trait is included on your application's
App\Models\User
model by default:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
}
The notify
method that is provided by this trait expects
to receive a notification instance:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
Tip!! Remember, you may use the
Notifiable
trait on any of your models. You are not limited to only including it on yourUser
model.
Using The Notification Facade
Alternatively, you may send notifications via the
Notification
facade. This
approach is useful when you need to send a notification to multiple
notifiable entities such as a collection of users. To send notifications
using the facade, pass all of the notifiable entities and the
notification instance to the send
method:
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));
You can also send notifications immediately using the
sendNow
method. This method will send the notification
immediately even if the notification implements the
ShouldQueue
interface:
Notification::sendNow($developers, new DeploymentCompleted($deployment));
Specifying Delivery Channels
Every notification class has a via
method that
determines on which channels the notification will be delivered.
Notifications may be sent on the mail
,
database
, broadcast
, nexmo
, and
slack
channels.
Tip!! If you would like to use other delivery channels such as Telegram or Pusher, check out the community driven Laravel Notification Channels website.
The via
method receives a $notifiable
instance, which will be an instance of the class to which the
notification is being sent. You may use $notifiable
to
determine which channels the notification should be delivered on:
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
Queueing Notifications
Note: Before queueing notifications you should configure your queue and start a worker.
Sending notifications can take time, especially if the channel needs
to make an external API call to deliver the notification. To speed up
your application's response time, let your notification be queued by
adding the ShouldQueue
interface and Queueable
trait to your class. The interface and trait are already imported for
all notifications generated using the make:notification
command, so you may immediately add them to your notification class:
<?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;
// ...
}
Once the ShouldQueue
interface has been added to your
notification, you may send the notification like normal. Laravel will
detect the ShouldQueue
interface on the class and
automatically queue the delivery of the notification:
$user->notify(new InvoicePaid($invoice));
If you would like to delay the delivery of the notification, you may
chain the delay
method onto your notification
instantiation:
$delay = now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($delay));
You may pass an array to the delay
method to specify the
delay amount for specific channels:
$user->notify((new InvoicePaid($invoice))->delay([
'mail' => now()->addMinutes(5),
'sms' => now()->addMinutes(10),
]));
When queueing notifications, a queued job will be created for each recipient and channel combination. For example, six jobs will be dispatched to the queue if your notification has three recipients and two channels.
Customizing The Notification Queue Connection
By default, queued notifications will be queued using your
application's default queue connection. If you would like to specify a
different connection that should be used for a particular notification,
you may define a $connection
property on the notification
class:
/**
* The name of the queue connection to use when queueing the notification.
*
* @var string
*/
public $connection = 'redis';
Customizing Notification Channel Queues
If you would like to specify a specific queue that should be used for
each notification channel supported by the notification, you may define
a viaQueues
method on your notification. This method should
return an array of channel name / queue name pairs:
/**
* Determine which queues should be used for each notification channel.
*
* @return array
*/
public function viaQueues()
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}
Queued Notifications & Database Transactions
When queued notifications are dispatched within database transactions, they may be processed by the queue before the database transaction has committed. When this happens, any updates you have made to models or database records during the database transaction may not yet be reflected in the database. In addition, any models or database records created within the transaction may not exist in the database. If your notification depends on these models, unexpected errors can occur when the job that sends the queued notification is processed.
If your queue connection's after_commit
configuration
option is set to false
, you may still indicate that a
particular queued notification should be dispatched after all open
database transactions have been committed by calling the
afterCommit
method when sending the notification:
use App\Notifications\InvoicePaid;
$user->notify((new InvoicePaid($invoice))->afterCommit());
Alternatively, you may call the afterCommit
method from
your notification's constructor:
<?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.
*
* @return void
*/
public function __construct()
{
$this->afterCommit();
}
}
Tip!! To learn more about working around these issues, please review the documentation regarding queued jobs and database transactions.
Determining If A Queued Notification Should Be Sent
After a queued notification has been dispatched for the queue for background processing, it will typically be accepted by a queue worker and sent to its intended recipient.
However, if you would like to make the final determination on whether
the queued notification should be sent after it is being processed by a
queue worker, you may define a shouldSend
method on the
notification class. If this method returns false
, the
notification will not be sent:
/**
* Determine if the notification should be sent.
*
* @param mixed $notifiable
* @param string $channel
* @return bool
*/
public function shouldSend($notifiable, $channel)
{
return $this->invoice->isPaid();
}
On-Demand Notifications
Sometimes you may need to send a notification to someone who is not
stored as a "user" of your application. Using the
Notification
facade's route
method, you may
specify ad-hoc notification routing information before sending the
notification:
Notification::route('mail', 'taylor@example.com')
->route('nexmo', '5555555555')
->route('slack', 'https://hooks.slack.com/services/...')
->notify(new InvoicePaid($invoice));
If you would like to provide the recipient's name when sending an
on-demand notification to the mail
route, you may provide
an array that contains the email address as the key and the name as the
value of the first element in the array:
Notification::route('mail', [
'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));
Mail Notifications
Formatting Mail Messages
If a notification supports being sent as an email, you should define
a toMail
method on the notification class. This method will
receive a $notifiable
entity and should return an
Illuminate\Notifications\Messages\MailMessage
instance.
The MailMessage
class contains a few simple methods to
help you build transactional email messages. Mail messages may contain
lines of text as well as a "call to action". Let's take a look at an
example toMail
method:
/**
* Get the mail representation of 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!');
}
Tip!! Note we are using
$this->invoice->id
in ourtoMail
method. You may pass any data your notification needs to generate its message into the notification's constructor.
In this example, we register a greeting, a line of text, a call to
action, and then another line of text. These methods provided by the
MailMessage
object make it simple and fast to format small
transactional emails. The mail channel will then translate the message
components into a beautiful, responsive HTML email template with a
plain-text counterpart. Here is an example of an email generated by the
mail
channel:
Tip!! When sending mail notifications, be sure to set the
name
configuration option in yourconfig/app.php
configuration file. This value will be used in the header and footer of your mail notification messages.
Other Mail Notification Formatting Options
Instead of defining the "lines" of text in the notification class,
you may use the view
method to specify a custom template
that should be used to render the notification email:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.name', ['invoice' => $this->invoice]
);
}
You may specify a plain-text view for the mail message by passing the
view name as the second element of an array that is given to the
view
method:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
['emails.name.html', 'emails.name.plain'],
['invoice' => $this->invoice]
);
}
Error Messages
Some notifications inform users of errors, such as a failed invoice
payment. You may indicate that a mail message is regarding an error by
calling the error
method when building your message. When
using the error
method on a mail message, the call to
action button will be red instead of black:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Message
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Notification Subject')
->line('...');
}
Customizing The Sender
By default, the email's sender / from address is defined in the
config/mail.php
configuration file. However, you may
specify the from address for a specific notification using the
from
method:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}
Customizing The Recipient
When sending notifications via the mail
channel, the
notification system will automatically look for an email
property on your notifiable entity. You may customize which email
address is used to deliver the notification by defining a
routeNotificationForMail
method on the notifiable
entity:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the mail channel.
*
* @param \Illuminate\Notifications\Notification $notification
* @return array|string
*/
public function routeNotificationForMail($notification)
{
// Return email address only...
return $this->email_address;
// Return email address and name...
return [$this->email_address => $this->name];
}
}
Customizing The Subject
By default, the email's subject is the class name of the notification
formatted to "Title Case". So, if your notification class is named
InvoicePaid
, the email's subject will be
Invoice Paid
. If you would like to specify a different
subject for the message, you may call the subject
method
when building your message:
/**
* 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('...');
}
Customizing The Mailer
By default, the email notification will be sent using the default
mailer defined in the config/mail.php
configuration file.
However, you may specify a different mailer at runtime by calling the
mailer
method when building your message:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
Customizing The Templates
You can modify the HTML and plain-text template used by mail
notifications by publishing the notification package's resources. After
running this command, the mail notification templates will be located in
the resources/views/vendor/notifications
directory:
php artisan vendor:publish --tag=laravel-notifications
Attachments
To add attachments to an email notification, use the
attach
method while building your message. The
attach
method accepts the absolute path to the file as its
first argument:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
When attaching files to a message, you may also specify the display
name and / or MIME type by passing an array
as the second
argument to the attach
method:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
Unlike attaching files in mailable objects, you may not attach a file
directly from a storage disk using attachFromStorage
. You
should rather use the attach
method with an absolute path
to the file on the storage disk. Alternatively, you could return a mailable from the
toMail
method:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorage('/path/to/file');
}
Raw Data Attachments
The attachData
method may be used to attach a raw string
of bytes as an attachment. When calling the attachData
method, you should provide the filename that should be assigned to the
attachment:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Using Mailables
If needed, you may return a full mailable
object from your notification's toMail
method. When
returning a Mailable
instead of a MailMessage
,
you will need to specify the message recipient using the mailable
object's to
method:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Mailables & On-Demand Notifications
If you are sending an on-demand
notification, the $notifiable
instance given to the
toMail
method will be an instance of
Illuminate\Notifications\AnonymousNotifiable
, which offers
a routeNotificationFor
method that may be used to retrieve
the email address the on-demand notification should be sent to:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
$address = $notifiable instanceof AnonymousNotifiable
? $notifiable->routeNotificationFor('mail')
: $notifiable->email;
return (new InvoicePaidMailable($this->invoice))
->to($address);
}
Previewing Mail Notifications
When designing a mail notification template, it is convenient to
quickly preview the rendered mail message in your browser like a typical
Blade template. For this reason, Laravel allows you to return any mail
message generated by a mail notification directly from a route closure
or controller. When a MailMessage
is returned, it will be
rendered and displayed in the browser, allowing you to quickly preview
its design without needing to send it to an actual email address:
use App\Models\Invoice;
use App\Notifications\InvoicePaid;
Route::get('/notification', function () {
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))
->toMail($invoice->user);
});
Markdown Mail Notifications
Markdown mail notifications allow you to take advantage of the pre-built templates of mail notifications, while giving you more freedom to write longer, customized messages. Since the messages are written in Markdown, Laravel is able to render beautiful, responsive HTML templates for the messages while also automatically generating a plain-text counterpart.
Generating The Message
To generate a notification with a corresponding Markdown template,
you may use the --markdown
option of the
make:notification
Artisan command:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
Like all other mail notifications, notifications that use Markdown
templates should define a toMail
method on their
notification class. However, instead of using the line
and
action
methods to construct the notification, use the
markdown
method to specify the name of the Markdown
template that should be used. An array of data you wish to make
available to the template may be passed as the method's second
argument:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
Writing The Message
Markdown mail notifications use a combination of Blade components and Markdown syntax which allow you to easily construct notifications while leveraging Laravel's pre-crafted notification 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 Component
The button component renders a centered button link. The component
accepts two arguments, a url
and an optional
color
. Supported colors are primary
,
green
, and red
. You may add as many button
components to a notification as you wish:
@component('mail::button', ['url' => $url, 'color' => 'green'])
View Invoice
@endcomponent
Panel Component
The panel component renders the given block of text in a panel that has a slightly different background color than the rest of the notification. This allows you to draw attention to a given block of text:
@component('mail::panel')
This is the panel content.
@endcomponent
Table Component
The table component allows you to transform a Markdown table into an HTML table. The component accepts the Markdown table as its content. Table column alignment is supported using the default Markdown table alignment syntax:
@component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
@endcomponent
Customizing The Components
You may export all of the Markdown notification components to your
own application for customization. To export the components, use the
vendor:publish
Artisan command to publish the
laravel-mail
asset tag:
php artisan vendor:publish --tag=laravel-mail
This command will publish the Markdown mail components to the
resources/views/vendor/mail
directory. The
mail
directory will contain an html
and a
text
directory, each containing their respective
representations of every available component. You are free to customize
these components however you like.
Customizing The CSS
After exporting the components, the
resources/views/vendor/mail/html/themes
directory will
contain a default.css
file. You may customize the CSS in
this file and your styles will automatically be in-lined within the HTML
representations of your Markdown notifications.
If you would like to build an entirely new theme for Laravel's
Markdown components, you may place a CSS file within the
html/themes
directory. After naming and saving your CSS
file, update the theme
option of the mail
configuration file to match the name of your new theme.
To customize the theme for an individual notification, you may call
the theme
method while building the notification's mail
message. The theme
method accepts the name of the theme
that should be used when sending the notification:
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
Database Notifications
Prerequisites
The database
notification channel stores the
notification information in a database table. This table will contain
information such as the notification type as well as a JSON data
structure that describes the notification.
You can query the table to display the notifications in your
application's user interface. But, before you can do that, you will need
to create a database table to hold your notifications. You may use the
notifications:table
command to generate a migration with the proper table schema:
php artisan notifications:table
php artisan migrate
Formatting Database Notifications
If a notification supports being stored in a database table, you
should define a toDatabase
or toArray
method
on the notification class. This method will receive a
$notifiable
entity and should return a plain PHP array. The
returned array will be encoded as JSON and stored in the
data
column of your notifications
table. Let's
take a look at an example toArray
method:
/**
* 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
The toArray
method is also used by the
broadcast
channel to determine which data to broadcast to
your JavaScript powered frontend. If you would like to have two
different array representations for the database
and
broadcast
channels, you should define a
toDatabase
method instead of a toArray
method.
Accessing The Notifications
Once notifications are stored in the database, you need a convenient
way to access them from your notifiable entities. The
Illuminate\Notifications\Notifiable
trait, which is
included on Laravel's default App\Models\User
model,
includes a notifications
Eloquent relationship that
returns the notifications for the entity. To fetch notifications, you
may access this method like any other Eloquent relationship. By default,
notifications will be sorted by the created_at
timestamp
with the most recent notifications at the beginning of the
collection:
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
If you want to retrieve only the "unread" notifications, you may use
the unreadNotifications
relationship. Again, these
notifications will be sorted by the created_at
timestamp
with the most recent notifications at the beginning of the
collection:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
Tip!! To access your notifications from your JavaScript client, you should define a notification controller for your application which returns the notifications for a notifiable entity, such as the current user. You may then make an HTTP request to that controller's URL from your JavaScript client.
Marking Notifications As Read
Typically, you will want to mark a notification as "read" when a user
views it. The Illuminate\Notifications\Notifiable
trait
provides a markAsRead
method, which updates the
read_at
column on the notification's database record:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
However, instead of looping through each notification, you may use
the markAsRead
method directly on a collection of
notifications:
$user->unreadNotifications->markAsRead();
You may also use a mass-update query to mark all of the notifications as read without retrieving them from the database:
$user = App\Models\User::find(1);
$user->unreadNotifications()->update(['read_at' => now()]);
You may delete
the notifications to remove them from the
table entirely:
$user->notifications()->delete();
Broadcast Notifications
Prerequisites
Before broadcasting notifications, you should configure and be familiar with Laravel's event broadcasting services. Event broadcasting provides a way to react to server-side Laravel events from your JavaScript powered frontend.
Formatting Broadcast Notifications
The broadcast
channel broadcasts notifications using
Laravel's event broadcasting services,
allowing your JavaScript powered frontend to catch notifications in
realtime. If a notification supports broadcasting, you can define a
toBroadcast
method on the notification class. This method
will receive a $notifiable
entity and should return a
BroadcastMessage
instance. If the toBroadcast
method does not exist, the toArray
method will be used to
gather the data that should be broadcast. The returned data will be
encoded as JSON and broadcast to your JavaScript powered frontend. Let's
take a look at an example toBroadcast
method:
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 are queued for broadcasting. If you would
like to configure the queue connection or queue name that is used to
queue the broadcast operation, you may use the onConnection
and onQueue
methods of the
BroadcastMessage
:
return (new BroadcastMessage($data))
->onConnection('sqs')
->onQueue('broadcasts');
Customizing The Notification Type
In addition to the data you specify, all broadcast notifications also
have a type
field containing the full class name of the
notification. If you would like to customize the notification
type
, you may define a broadcastType
method on
the notification class:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Get the type of the notification being broadcast.
*
* @return string
*/
public function broadcastType()
{
return 'broadcast.message';
}
Listening For Notifications
Notifications will broadcast on a private channel formatted using a
{notifiable}.{id}
convention. So, if you are sending a
notification to an App\Models\User
instance with an ID of
1
, the notification will be broadcast on the
App.Models.User.1
private channel. When using Laravel Echo, you
may easily listen for notifications on a channel using the
notification
method:
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
Customizing The Notification Channel
If you would like to customize which channel that an entity's
broadcast notifications are broadcast on, you may define a
receivesBroadcastNotificationsOn
method on the notifiable
entity:
<?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.
*
* @return string
*/
public function receivesBroadcastNotificationsOn()
{
return 'users.'.$this->id;
}
}
SMS Notifications
Prerequisites
Sending SMS notifications in Laravel is powered by Vonage (formerly known as Nexmo).
Before you can send notifications via Vonage, you need to install the
laravel/nexmo-notification-channel
and
nexmo/laravel
Composer packages
composer require laravel/nexmo-notification-channel nexmo/laravel
The nexmo/laravel
package includes its
own configuration file. However, you are not required to export this
configuration file to your own application. You can simply use the
NEXMO_KEY
and NEXMO_SECRET
environment
variables to set your Vonage public and secret key.
Next, you will need to add a nexmo
configuration entry
to your config/services.php
configuration file. You may
copy the example configuration below to get started:
'nexmo' => [
'sms_from' => '15556666666',
],
The sms_from
option is the phone number that your SMS
messages will be sent from. You should generate a phone number for your
application in the Vonage control panel.
Formatting SMS Notifications
If a notification supports being sent as an SMS, you should define a
toNexmo
method on the notification class. This method will
receive a $notifiable
entity and should return an
Illuminate\Notifications\Messages\NexmoMessage
instance:
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content');
}
Unicode Content
If your SMS message will contain unicode characters, you should call
the unicode
method when constructing the
NexmoMessage
instance:
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your unicode message')
->unicode();
}
Formatting Shortcode Notifications
Laravel also supports sending shortcode notifications, which are
pre-defined message templates in your Vonage account. To send a
shortcode SMS notification, you should define a toShortcode
method on your notification class. From within this method, you may
return an array specifying the type of notification (alert
,
2fa
, or marketing
) as well as the custom
values that will populate the template:
/**
* Get the Vonage / Shortcode representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toShortcode($notifiable)
{
return [
'type' => 'alert',
'custom' => [
'code' => 'ABC123',
],
];
}
Tip!! Like routing SMS Notifications, you should implement the
routeNotificationForShortcode
method on your notifiable model.
Customizing The "From" Number
If you would like to send some notifications from a phone number that
is different from the phone number specified in your
config/services.php
file, you may call the
from
method on a NexmoMessage
instance:
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content')
->from('15554443333');
}
Adding a Client Reference
If you would like to keep track of costs per user, team, or client, you may add a "client reference" to the notification. Vonage will allow you to generate reports using this client reference so that you can better understand a particular customer's SMS usage. The client reference can be any string up to 40 characters:
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->clientReference((string) $notifiable->id)
->content('Your SMS message content');
}
Routing SMS Notifications
To route Vonage notifications to the proper phone number, define a
routeNotificationForNexmo
method on your notifiable
entity:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Nexmo channel.
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForNexmo($notification)
{
return $this->phone_number;
}
}
Slack Notifications
Prerequisites
Before you can send notifications via Slack, you must install the Slack notification channel via Composer:
composer require laravel/slack-notification-channel
You will also need to create a Slack App for your team. After creating the App, you should configure an "Incoming Webhook" for the workspace. Slack will then provide you with a webhook URL that you may use when routing Slack notifications.
Formatting Slack Notifications
If a notification supports being sent as a Slack message, you should
define a toSlack
method on the notification class. This
method will receive a $notifiable
entity and should return
an Illuminate\Notifications\Messages\SlackMessage
instance.
Slack messages may contain text content as well as an "attachment" that
formats additional text or an array of fields. Let's take a look at a
basic toSlack
example:
/**
* Get the Slack representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content('One of your invoices has been paid!');
}
Slack Attachments
You may also add "attachments" to Slack messages. Attachments provide richer formatting options than simple text messages. In this example, we will send an error notification about an exception that occurred in an application, including a link to view more details about the exception:
/**
* Get the Slack representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\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.');
});
}
Attachments also allow you to specify an array of data that should be presented to the user. The given data will be presented in a table-style format for easy reading:
/**
* 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:',
]);
});
}
Markdown Attachment Content
If some of your attachment fields contain Markdown, you may use the
markdown
method to instruct Slack to parse and display the
given attachment fields as Markdown formatted text. The values accepted
by this method are: pretext
, text
, and / or
fields
. For more information about Slack attachment
formatting, check out the 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']);
});
}
Routing Slack Notifications
To route Slack notifications to the proper Slack team and channel,
define a routeNotificationForSlack
method on your
notifiable entity. This should return the webhook URL to which the
notification should be delivered. Webhook URLs may be generated by
adding an "Incoming Webhook" service to your Slack team:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Route notifications for the Slack channel.
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForSlack($notification)
{
return 'https://hooks.slack.com/services/...';
}
}
Localizing Notifications
Laravel allows you to send notifications in a locale other than the HTTP request's current locale, and will even remember this locale if the notification is queued.
To accomplish this, the
Illuminate\Notifications\Notification
class offers a
locale
method to set the desired language. The application
will change into this locale when the notification is being evaluated
and then revert back to the previous locale when evaluation is
complete:
$user->notify((new InvoicePaid($invoice))->locale('es'));
Localization of multiple notifiable entries may also be achieved via
the Notification
facade:
Notification::locale('es')->send(
$users, new InvoicePaid($invoice)
);
User Preferred Locales
Sometimes, applications store each user's preferred locale. By
implementing the HasLocalePreference
contract on your
notifiable model, you may instruct Laravel to use this stored locale
when sending a notification:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Get the user's preferred locale.
*
* @return string
*/
public function preferredLocale()
{
return $this->locale;
}
}
Once you have implemented the interface, Laravel will automatically
use the preferred locale when sending notifications and mailables to the
model. Therefore, there is no need to call the locale
method when using this interface:
$user->notify(new InvoicePaid($invoice));
Notification Events
Notification Sending Event
When a notification is sending, the
Illuminate\Notifications\Events\NotificationSending
event is dispatched by the notification system.
This contains the "notifiable" entity and the notification instance
itself. You may register listeners for this event in your application's
EventServiceProvider
:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSending' => [
'App\Listeners\CheckNotificationStatus',
],
];
The notification will not be sent if an event listener for the
NotificationSending
event returns false
from
its handle
method:
use Illuminate\Notifications\Events\NotificationSending;
/**
* Handle the event.
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
return false;
}
Within an event listener, you may access the notifiable
,
notification
, and channel
properties on the
event to learn more about the notification recipient or the notification
itself:
/**
* Handle the event.
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
// $event->channel
// $event->notifiable
// $event->notification
}
Notification Sent Event
When a notification is sent, the
Illuminate\Notifications\Events\NotificationSent
event is dispatched by the notification system.
This contains the "notifiable" entity and the notification instance
itself. You may register listeners for this event in your
EventServiceProvider
:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\LogNotification',
],
];
Tip!! After registering listeners in your
EventServiceProvider
, use theevent:generate
Artisan command to quickly generate listener classes.
Within an event listener, you may access the notifiable
,
notification
, channel
, and
response
properties on the event to learn more about the
notification recipient or the notification itself:
/**
* Handle the event.
*
* @param \Illuminate\Notifications\Events\NotificationSent $event
* @return void
*/
public function handle(NotificationSent $event)
{
// $event->channel
// $event->notifiable
// $event->notification
// $event->response
}
Custom Channels
Laravel ships with a handful of notification channels, but you may
want to write your own drivers to deliver notifications via other
channels. Laravel makes it simple. To get started, define a class that
contains a send
method. The method should receive two
arguments: a $notifiable
and a
$notification
.
Within the send
method, you may call methods on the
notification to retrieve a message object understood by your channel and
then send the notification to the $notifiable
instance
however you wish:
<?php
namespace App\Notifications;
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 the $notifiable instance...
}
}
Once your notification channel class has been defined, you may return
the class name from the via
method of any of your
notifications. In this example, the toVoice
method of your
notification can return whatever object you choose to represent voice
messages. For example, you might define your own
VoiceMessage
class to represent these messages:
<?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.
*
* @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)
{
// ...
}
}