git f8eec0aa795d4fc21706d92e03dbaf0d6a3f4f30
- Введение
- Генерация уведомлений
- Отправка уведомлений
- Почтовые уведомления
- Почтовые уведомления с разметкой Markdown
- Уведомления через канал
database
- Трансляция уведомлений
- Уведомления через SMS
- Уведомления через Slack
- Локализация уведомлений
- События уведомления
- Пользовательские каналы уведомлений
В дополнение к поддержке отправки электронной почты, Laravel обеспечивает поддержку отправки уведомлений по различным каналам доставки, включая электронную почту, SMS (через Vonage, бывший Nexmo) и Slack. Кроме того, сообществом было создано множество каналов уведомлений для отправки уведомлений по десяткам различных каналов! Уведомления также могут храниться в базе данных, поэтому они могут быть отображены в вашем веб-интерфейсе.
Как правило, уведомления должны быть короткими информационными сообщениями, которые уведомляют пользователей о том, что произошло в вашем приложении. Например, если вы пишете приложение для выставления счетов, то вы можете отправить своим пользователям уведомление «Счет оплачен» по каналам электронной почты и SMS.
В Laravel каждое уведомление представлено единым классом. Чтобы сгенерировать новое уведомление, используйте команду make:notification
Artisan. Эта команда поместит новый класс уведомления в каталог app/Notifications
вашего приложения. Если этот каталог не существует в вашем приложении, то Laravel предварительно создаст его:
php artisan make:notification InvoicePaid
Каждый класс уведомления содержит метод via
и переменное количество методов формирования сообщений, таких как toMail
или toDatabase
, которые преобразуют уведомление в сообщение, адаптированное для этого конкретного канала.
Уведомления могут быть отправлены двумя способами: с использованием метода notify
трейта Notifiable
или с помощью фасада Notification
. Трейт 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));
{tip} Помните, что вы можете использовать трейт
Notifiable
в любой из ваших моделей. Вы не ограничены использованием его только в моделиUser
.
Как вариант, вы можете отправлять уведомления через фасад Notification
. Этот подход полезен при отправке уведомления нескольким уведомляемым объектам, например группе пользователей. Чтобы отправлять уведомления с помощью фасада, передайте все уведомляемые сущности и экземпляр уведомления методу send
:
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));
Вы также можете немедленно отправлять уведомления, используя метод sendNow
. Этот метод немедленно отправит уведомление, даже если оно реализует интерфейс ShouldQueue
:
Notification::sendNow($developers, new DeploymentCompleted($deployment));
Каждый класс уведомлений имеет метод via
, который определяет, по каким каналам будет доставлено уведомление. Уведомления можно отправлять по каналам mail
, database
, broadcast
, nexmo
и slack
.
{tip} Если вы хотите использовать другие каналы доставки, такие как Telegram или Pusher, то посетите веб-сайт сообщества Laravel Notification Channels.
Метод via
получает экземпляр $notifiable
, представляющий экземпляр класса, которому отправляется уведомление. Вы можете использовать $notifiable
, чтобы определить, по каким каналам должно доставляться уведомление:
/**
* Получить каналы доставки уведомлений.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return $notifiable->prefers_sms ? ['nexmo'] : ['mail', 'database'];
}
{note} Перед отправкой уведомлений в очередь вы должны настроить и запустить обработчик очереди.
Отправка уведомлений может занять время, особенно если каналу необходимо выполнить внешний вызов 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),
]));
При постановке уведомлений в очередь для каждого получателя и комбинации каналов создается задание в очереди. Например, в очередь будет отправлено шесть заданий, если у вашего уведомления три получателя и два канала.
По умолчанию отложенные уведомления будут помещены в очередь с использованием соединения очереди по умолчанию для вашего приложения. Если вы хотите указать другое соединение, которое должно использоваться для определенного уведомления, то вы можете определить свойство $connection
в классе уведомления:
/**
* Имя соединения очереди, которое будет использоваться отложенным уведомлением.
*
* @var string
*/
public $connection = 'redis';
Если вы хотите указать конкретную очередь, которая должна использоваться для каждого канала уведомления, поддерживаемого уведомлением, то вы можете определить метод viaQueues
в своем уведомлении. Этот метод должен возвращать массив пар имя канала / имя очереди:
/**
* Определить, какие очереди следует использовать для каждого канала уведомления.
*
* @return array
*/
public function viaQueues()
{
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.
*
* @return void
*/
public function __construct()
{
$this->afterCommit();
}
}
{tip} Чтобы узнать больше о том, как обойти эти проблемы, просмотрите документацию, касающуюся заданий в очереди и транзакций базы данных.
После того как уведомление из очереди было отправлено для фоновой обработки, оно обычно принимается работником очереди и отправляется предполагаемому получателю.
Однако, если вы хотите окончательно определить, следует ли отправлять уведомление в очереди после его обработки работником очереди, вы можете определить метод shouldSend
в классе уведомлений. Если этот метод возвращает false
, уведомление не будет отправлено:
/**
* Определите, нужно ли отправлять уведомление.
*
* @param mixed $notifiable
* @param string $channel
* @return bool
*/
public function shouldSend($notifiable, $channel)
{
return $this->invoice->isPaid();
}
По желанию можно отправить уведомление кому-то, кто не сохранен как «пользователь» вашего приложения. Используя метод route
фасада Notification
, вы можете указать информацию о маршрутизации специального уведомления перед отправкой уведомления:
Notification::route('mail', 'taylor@example.com')
->route('nexmo', '5555555555')
->route('slack', 'https://hooks.slack.com/services/...')
->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
:
/**
* Получить содержимое почтового уведомления.
*
* @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} Обратите внимание, что мы используем
$this->invoice->id
в нашем методеtoMail
. Вы можете передать любые данные, которые необходимы вашему уведомлению для генерации сообщения, в конструктор уведомления.
В этом примере мы регистрируем приветствие, строку текста, призыв к действию, а затем еще одну строку текста. Эти методы, предоставляемые объектом MailMessage
, упрощают и ускоряют формирование небольших транзакционных электронных писем. Затем канал mail
преобразует компоненты сообщения в красивый, отзывчивый HTML-шаблон сообщения электронной почты с аналогом в виде обычного текста. Вот пример электронного письма, созданного каналом mail
:
{tip} При отправке почтовых уведомлений не забудьте установить параметр
name
в вашем конфигурационном файлеconfig/app.php
. Это значение будет использоваться в верхнем и нижнем колонтитулах ваших почтовых уведомлений.
Вместо определения «строк» текста в классе уведомления, вы можете использовать метод view
, чтобы указать собственный шаблон, который следует использовать для отображения почтового уведомления:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->view(
'emails.name', ['invoice' => $this->invoice]
);
}
Вы можете определить текстовое содержимое для почтового сообщения, указав имя представления в качестве второго элемента массива, передаваемого методу view
:
/**
* Получить содержимое почтового уведомления.
*
* @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
при построении вашего сообщения. При использовании метода error
в почтовом сообщении кнопка призыва к действию будет красной вместо черной:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Message
*/
public function toMail($notifiable)
{
return (new MailMessage)
->error()
->subject('Notification Subject')
->line('...');
}
По умолчанию адрес отправителя электронного письма определяется в конфигурационном файле config/mail.php
. Однако вы можете указать адрес отправителя для конкретного уведомления с помощью метода from
:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
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;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для почтового канала.
*
* @param \Illuminate\Notifications\Notification $notification
* @return array|string
*/
public function routeNotificationForMail($notification)
{
// Вернуть только адрес электронной почты ...
return $this->email_address;
// Вернуть адрес электронной почты и имя ...
return [$this->email_address => $this->name];
}
}
По умолчанию темой электронного письма является название класса уведомления в регистре «Title Case». Итак, если ваш класс уведомлений называется InvoicePaid
, то темой электронного письма будет «Invoice Paid». Если вы хотите указать другую тему для сообщения, то вы можете вызвать метод subject
при создании своего сообщения:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
По умолчанию уведомление по электронной почте будет отправлено с использованием почтового драйвера по умолчанию, определенной в конфигурационном файле config/mail.php
. Однако вы можете указать другой почтовый драйвер во время выполнения, вызвав метод mailer
при создании вашего сообщения:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
Вы можете изменить шаблон из HTML и обычного текста, используемый для почтовых уведомлений, опубликовав необходимые ресурсы уведомления. После выполнения этой команды шаблоны почтовых уведомлений будут расположены в каталоге resources/views/vendor/notifications
:
php artisan vendor:publish --tag=laravel-notifications
Чтобы добавить вложения к почтовому уведомлению, используйте метод attach
при создании сообщения. Метод attach
принимает абсолютный путь к файлу в качестве своего первого аргумента:
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
При прикреплении файлов к сообщению вы также можете указать отображаемое имя и / или MIME-тип, передав массив в качестве второго аргумента методу attach
:
/**
* Получить содержимое почтового уведомления.
*
* @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',
]);
}
В отличие от прикрепления файлов к почтовым отправлениям, вы не можете прикреплять файл непосредственно с диска файлового хранилища с помощью attachFromStorage
. Лучше использовать метод attach
с абсолютным путем к файлу на диске. В качестве альтернативы вы можете вернуть отправление из метода toMail
:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorage('/path/to/file');
}
Метод attachData
используется для присоединения необработанной строки в качестве вложения. При вызове метода attachData
вы должны указать имя файла, которое должно быть присвоено вложению:
/**
* Получить содержимое почтового уведомления.
*
* @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',
]);
}
При необходимости вы можете вернуть полный объект почтового отправления из метода toMail
вашего уведомления. При возврате Mailable
вместо MailMessage
вам нужно будет указать получателя сообщения с помощью метода to
объекта почтового отправления:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Получить содержимое почтового уведомления.
*
* @param mixed $notifiable
* @return Mailable
*/
public function toMail($notifiable)
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Если вы отправляете уведомление по запросу, то экземпляр $notifiable
, переданный методу toMail
, будет экземпляром Illuminate\Notifications\AnonymousNotifiable
, содержащий метод routeNotificationFor
, который можно использовать для получения адреса электронной почты для отправления уведомления по запросу:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
/**
* Получить содержимое почтового уведомления.
*
* @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);
}
При разработке шаблона почтового уведомления удобно быстро просмотреть визуализированное почтовое сообщение в браузере, как типичный шаблон 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
Artisan:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
Как и все другие почтовые уведомления, уведомления, использующие шаблоны Markdown, должны определять метод toMail
в своем классе уведомлений. Однако вместо использования методов line
и action
для создания уведомления используйте метод markdown
, чтобы указать имя шаблона Markdown, который следует использовать. Массив данных, который вы хотите сделать доступным для шаблона, может быть передан в качестве второго аргумента метода:
/**
* Получить содержимое почтового уведомления.
*
* @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]);
}
Почтовые уведомления Markdown используют комбинацию компонентов Blade и синтаксиса Markdown, которые позволяют легко создавать почтовые уведомления, используя предварительно созданные компоненты уведомлений Laravel:
@component('mail::message')
# Invoice Paid
Your invoice has been paid!
@component('mail::button', ['url' => $url])
View Invoice
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
Компонент кнопки отображает ссылку на кнопку по центру. Компонент принимает два аргумента: url
и необязательный color
. Поддерживаемые цвета: primary
, green
, и red
. Вы можете добавить к уведомлению столько компонентов кнопки, сколько захотите:
@component('mail::button', ['url' => $url, 'color' => 'green'])
View Invoice
@endcomponent
Компонент панели отображает указанный блок текста на панели, цвет фона которой немного отличается от цвета остальной части сообщения. Это позволяет привлечь внимание к указанному блоку текста:
@component('mail::panel')
This is the panel content.
@endcomponent
Компонент таблицы позволяет преобразовать таблицу Markdown в таблицу HTML. Компонент принимает в качестве содержимого таблицу Markdown. Выравнивание столбцов таблицы поддерживается с использованием синтаксиса выравнивания таблицы Markdown по умолчанию:
@component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
@endcomponent
Вы можете экспортировать все почтовые компоненты Markdown в собственное приложение для настройки. Чтобы экспортировать компоненты, используйте команду vendor:publish
Artisan с параметром --tag=laravel-mail
:
php artisan vendor:publish --tag=laravel-mail
Эта команда опубликует почтовые компоненты Markdown в каталоге resources/views/vendor/mail
. Каталог mail
будет содержать каталог html
и text
, каждый из которых содержит соответствующие представления каждого доступного компонента. Вы можете настроить эти компоненты по своему усмотрению.
После экспорта компонентов в каталоге resources/views/vendor/mail/html/themes
будет содержаться файл default.css
. Вы можете отредактировать CSS в этом файле, и ваши стили будут автоматически преобразованы во встроенные стили CSS в HTML-представлениях ваших почтовых сообщений Markdown.
Если вы хотите создать совершенно новую тему для компонентов Laravel Markdown, вы можете поместить файл CSS в каталог html/themes
. После присвоения имени и сохранения файла CSS обновите параметр theme
в файле конфигурации вашего приложения config/mail.php
, чтобы он соответствовал имени вашей новой темы.
Чтобы настроить тему для отдельного уведомления, вы можете вызвать метод theme
при создании почтового сообщения уведомления. Метод theme
принимает имя темы, которая должна использоваться при отправке уведомления:
/**
* Получить содержимое почтового уведомления.
*
* @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
хранит информацию уведомления в таблице базы данных. Эта таблица будет содержать такую информацию, как тип уведомления, а также JSON-структуру данных, которая описывает уведомление.
Вы можете запросить таблицу, чтобы отобразить уведомления в пользовательском интерфейсе вашего приложения. Но прежде чем вы сможете это сделать, вам нужно будет создать таблицу базы данных для хранения ваших уведомлений. Вы можете использовать команду notifications:table
для создания миграции с необходимой схемой таблицы:
php artisan notifications:table
php artisan migrate
Чтобы уведомление было сохранено в таблице базы данных, вы должны определить метод toDatabase
или toArray
в классе уведомления. Каждый из этих методов получает объект $notifiable
и должен возвращать простой массив PHP. Возвращенный массив будет закодирован как JSON и сохранен в столбце data
вашей таблицы notifications
. Давайте посмотрим на пример метода toArray
:
/**
* Получить массив данных уведомления.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
Метод toArray
также используется каналом broadcast
, чтобы определить, какие данные транслировать в JavaScript-приложение на клиентской стороне. Если вы хотите иметь два разных массива данных для каналов database
и broadcast
, то вы должны определить метод toDatabase
вместо метода toArray
.
После сохранения уведомления в базу данных, вам понадобится удобный способ доступа к нему из уведомляемых объектов. Трейт Illuminate\Notifications\Notifiable
, который по умолчанию расположен в модели App\Models\User
Laravel, содержит отношение notifications
Eloquent, возвращающее уведомления для объекта. Вы можете обратиться к этому методу, как и к любому другому отношению 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;
}
{tip} Чтобы получить доступ к уведомлениям в JavaScript-приложении на клиентской стороне, вы должны определить контроллер уведомлений для своего приложения, который возвращает уведомления для уведомляемого объекта, такого как текущий пользователь. Затем вы можете сделать HTTP-запрос к URL-адресу этого контроллера из своего JavaScript-приложения на клиентской стороне.
По желанию можно пометить уведомление как «прочитанное», когда пользователь его просматривает. Трейт 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();
Перед трансляцией уведомлений вы должны настроить и ознакомиться со службами трансляции событий Laravel. Трансляция событий – способ реагирования на серверные события Laravel из своего JavaScript-приложения на клиентской стороне.
Канал broadcast
транслирует уведомления с использованием служб трансляции событий Laravel, что позволяет вашему JavaScript-приложению на клиентской стороне улавливать уведомления в режиме реального времени. Если уведомление поддерживает трансляцию, то вы должны определить метод toBroadcast
в классе уведомления. Этот метод получит объект $notifiable
и должен вернуть экземпляр BroadcastMessage
. Если метод toBroadcast
не существует, то метод toArray
будет использоваться для сбора данных, которые следует транслировать. Возвращенные данные будут закодированы как JSON и переданы вашему JavaScript-приложению на клиентской стороне. Давайте посмотрим на пример метода toBroadcast
:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Получить содержимое транслируемого уведомления.
*
* @param mixed $notifiable
* @return BroadcastMessage
*/
public function toBroadcast($notifiable)
{
return new BroadcastMessage([
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
]);
}
Все транслируемые уведомления ставятся в очередь для трансляции. Если вы хотите изменить соединение очереди или имя очереди, которое используется для постановки в очередь трансляции, то вы можете использовать методы onConnection
и onQueue
экземпляра BroadcastMessage
:
return (new BroadcastMessage($data))
->onConnection('sqs')
->onQueue('broadcasts');
В дополнение к указанным вами данным все транслируемые уведомления также имеют поле type
, содержащее полное имя класса уведомления. Если вы хотите изменить type
уведомления, то вы можете определить метод broadcastType
в классе уведомления:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Получить тип транслируемого уведомления.
*
* @return string
*/
public function broadcastType()
{
return 'broadcast.message';
}
Уведомления будут транслироваться по частному каналу, в формате с использованием соглашения {notifiable}.{id}
. Итак, если вы отправляете уведомление экземпляру App\Models\User
с идентификатором 1
, то уведомление будет транслироваться по частному каналу App.Models.User.1
. При использовании Laravel Echo вы можете легко прослушивать уведомления канала, используя метод 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;
/**
* Каналы, по которым пользователь получает рассылку уведомлений.
*
* @return string
*/
public function receivesBroadcastNotificationsOn()
{
return 'users.'.$this->id;
}
}
Отправка SMS-уведомлений в Laravel обеспечивается Vonage (бывший Nexmo). Прежде чем вы сможете отправлять уведомления через Vonage, вам необходимо установить пакеты Composer:
composer require laravel/nexmo-notification-channel nexmo/laravel
Пакет nexmo/laravel
содержит собственный конфигурационный файл. Однако вам необязательно экспортировать этот файл конфигурации в собственное приложение. Вы можете просто использовать переменные окружения NEXMO_KEY
и NEXMO_SECRET
для установки публичного и секретного ключей Vonage.
Затем вам нужно будет добавить запись nexmo
в ваш конфигурационный файл config/services.php
. Для начала вам достаточно скопировать приведенный ниже пример конфигурации:
'nexmo' => [
'sms_from' => '15556666666',
],
Параметр sms_from
– это номер телефона, с которого будут отправляться ваши SMS-сообщения. Вы должны сгенерировать номер телефона для своего приложения в панели управления Vonage.
Если уведомление поддерживает отправку в виде SMS, то вы должны определить метод toNexmo
в классе уведомлений. Этот метод получит объект $notifiable
и должен вернуть экземпляр Illuminate\Notifications\Messages\NexmoMessage
:
/**
* Получить SMS-представление уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content');
}
Если ваше SMS-сообщение будет содержать символы Unicode, то вы должны вызвать метод unicode
при создании экземпляра NexmoMessage
:
/**
* Получить SMS-представление уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your unicode message')
->unicode();
}
Laravel также поддерживает отправку уведомлений с шорткодами, которые представляют собой предварительно определенные шаблоны сообщений в вашей учетной записи Vonage. Чтобы отправить такое SMS-уведомление, вы должны определить метод toShortcode
в своем классе уведомления. Из этого метода вы можете вернуть массив, определяющий тип уведомления (alert
, 2fa
или marketing
) и значения, которые будут заполнять шаблон:
/**
* Получить SMS-представление уведомления.
*
* @param mixed $notifiable
* @return array
*/
public function toShortcode($notifiable)
{
return [
'type' => 'alert',
'custom' => [
'code' => 'ABC123',
],
];
}
{tip} Как и в случае с маршрутизацией SMS-уведомлений, вам также следует реализовать метод
routeNotificationForShortcode
вашей уведомляемой модели.
Если вы хотите отправить уведомление с номера телефона, который отличается от номера телефона, указанного в вашем файле config/services.php
, то вы можете вызвать метод from
экземпляра NexmoMessage
:
/**
* Получить Vonage / SMS-представление уведомления.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->content('Your SMS message content')
->from('15554443333');
}
Если вы хотите отслеживать затраты на пользователя, команду или клиента, вы можете добавить в уведомление "ссылку на клиента". Vonage позволит вам создавать отчеты, используя эту ссылку клиента, чтобы вы могли лучше понять использование SMS конкретным клиентом. Ссылка на клиента может быть любой строкой до 40 символов:
/**
* Получить Vonage / SMS-представление уведомления.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toNexmo($notifiable)
{
return (new NexmoMessage)
->clientReference((string) $notifiable->id)
->content('Your SMS message content');
}
Для отправки уведомления с использованием Vonage на необходимый номер телефона, определите метод routeNotificationForNexmo
вашего уведомляемого объекта:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для канала Nexmo.
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForNexmo($notification)
{
return $this->phone_number;
}
}
Прежде чем вы сможете отправлять уведомления через Slack, вы должны установить канал уведомлений Slack через Composer:
composer require laravel/slack-notification-channel
Вам также потребуется создать Slack App для своей команды Slack. После создания приложения вы должны настроить «Incoming Webhook» для рабочей области. Затем Slack предоставит вам URL-адрес веб-перехватчика, который вы можете использовать при маршрутизации Slack-уведомлений.
Если уведомление поддерживает отправку в виде Slack-сообщения, то вы должны определить метод toSlack
класса уведомления. Этот метод получит объект $notifiable
и должен вернуть экземпляр Illuminate\Notifications\Messages\SlackMessage
. Сообщения Slack могут содержать текстовое содержимое, а также «вложение», которое формирует дополнительный текст или массив полей. Давайте посмотрим на пример toSlack
:
/**
* Получить представление Slack-уведомления.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content('One of your invoices has been paid!');
}
Вы также можете добавлять «вложения» к сообщениям Slack. Вложения предоставляют более широкие возможности форматирования, чем простые текстовые сообщения. В этом примере мы отправим уведомление об ошибке об исключении, которое произошло в приложении, включая ссылку для просмотра дополнительных сведений об исключении:
/**
* Получить представление Slack-уведомления.
*
* @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.');
});
}
Вложения также позволяют указать массив данных, которые должны быть представлены пользователю. Указанные данные будут представлены в формате таблицы для удобства при чтении:
/**
* Получить представление Slack-уведомления.
*
* @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, то вы можете использовать метод markdown
, чтобы указать Slack на синтаксический анализ и отображение указанных полей вложения как текста в формате Markdown. Значения, принимаемые этим методом: pretext
, text
и / или fields
. Дополнительные сведения о форматировании вложений Slack см. в документации API Slack:
/**
* Получить представление Slack-уведомления.
*
* @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 в соответствующую команду и канал, определите метод routeNotificationForSlack
вашего уведомляемого объекта. Этот метод должен вернуть URL-адрес веб-хука, на который должно быть доставлено уведомление. URL-адреса веб-хуков могут быть сгенерированы путем добавления сервиса «Incoming Webhook» в вашу команду Slack:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для канала Slack.
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForSlack($notification)
{
return 'https://hooks.slack.com/services/...';
}
}
Laravel позволяет отправлять уведомления, используя язык, отличный от текущего языка запроса, и даже будет помнить его, если уведомление находится в очереди.
Для этого класс 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
{
/**
* Получить предпочитаемую пользователем локализацию.
*
* @return string
*/
public function preferredLocale()
{
return $this->locale;
}
}
После того как вы реализовали интерфейс, Laravel будет автоматически использовать предпочтительный язык при отправке уведомлений и почтовых сообщений модели. Следовательно, при использовании этого интерфейса нет необходимости вызывать метод locale
:
$user->notify(new InvoicePaid($invoice));
При отправке уведомлений, система уведомлений запускает событие Illuminate\Notifications\Events\NotificationSending
. Событие содержит уведомляемую сущность и сам экземпляр уведомления. Вы можете зарегистрировать слушателей этого события в поставщике EventServiceProvider
:
/**
* Сопоставление прослушивателя событий для приложения.
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSending' => [
'App\Listeners\CheckNotificationStatus',
],
];
Уведомление не будет отправлено, если слушатель событий для события NotificationSending
вернет false
из своего метода handle
:
use Illuminate\Notifications\Events\NotificationSending;
/**
* Обработка события.
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
return false;
}
В слушателе событий вы можете получить доступ к свойствам notifiable
, notification
и channel
события, чтобы узнать больше о получателе уведомления или самом уведомлении:
/**
* Обработка события.
*
* @param \Illuminate\Notifications\Events\NotificationSending $event
* @return void
*/
public function handle(NotificationSending $event)
{
// $event->channel
// $event->notifiable
// $event->notification
}
Когда уведомление отправлено, система уведомлений запускает событие Illuminate\Notifications\Events\NotificationSent
. Событие содержит уведомляемую сущность и сам экземпляр уведомления. Вы можете зарегистрировать слушателей этого события в поставщике EventServiceProvider
:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\LogNotification',
],
];
{tip} После регистрации слушателей в вашем
EventServiceProvider
используйте командуevent:generate
Artisan, чтобы быстро сгенерировать классы слушателей.
В слушателе события вы можете получить доступ к свойствам notifiable
, notification
, channel
и response
события, чтобы узнать больше о получателе уведомления или самом уведомлении:
/**
* Обработать переданное событие.
*
* @param \Illuminate\Notifications\Events\NotificationSent $event
* @return void
*/
public function handle(NotificationSent $event)
{
// $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
{
/**
* Отправить переданное уведомление.
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return void
*/
public function send($notifiable, Notification $notification)
{
$message = $notification->toVoice($notifiable);
// Отправка уведомления экземпляру `$notifiable` ...
}
}
Как только ваш класс канала уведомления был определен, вы можете вернуть имя класса из метода 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;
/**
* Получить каналы доставки уведомлений.
*
* @param mixed $notifiable
* @return array|string
*/
public function via($notifiable)
{
return [VoiceChannel::class];
}
/**
* Получить содержимое голосового сообщения.
*
* @param mixed $notifiable
* @return VoiceMessage
*/
public function toVoice($notifiable)
{
// ...
}
}