Эта статья представляет собой небольшое руководство о том, как начать транслировать уведомления Laravel с помощью Pusher и получать их в React. У меня были проблемы с поиском всей необходимой документации, когда я сам начинал вещание. Поскольку я одновременно просматривал разные учебные пособия / статьи, мне было трудно отлаживать возникающие проблемы.
У меня есть работающее веб-приложение, созданное с помощью Laravel и React, и теперь мне нужно, чтобы мои пользователи получали уведомления в режиме реального времени.
Laravel предоставляет канал Pusher из коробки, и я решил использовать его. На тот момент я никогда не работал с сокетами (что отчасти печально, поскольку я был разработчиком (Laravel) в течение 4 лет), и я понятия не имел, как к этому подойти.
Я разделил задачу на несколько более мелких:
- Настроить Pusher и трансляцию в Laravel
- Создать класс (ы) уведомлений
- Добавьте Laravel Echo и PusherJS в React
- Подпишитесь на канал (ы)
Настроить трансляцию Pusher в Laravel
Мы также можем разбить эту задачу на меньшие:
- Установить Pusher
- Настройте файлы конфигурации и .env
- Настроить авторизацию канала
- Настроить модель пользователя
Прежде всего, нам нужно добавить в проект пакет Pusher composer.
composer require pusher/pusher-php-server "~3.0"
Во-вторых, давайте настроим файлы конфигурации и переменные среды.
В config/broadcasting.php
файле должна быть опция толкателя в подключениях:
'default' => env('BROADCAST_DRIVER', 'null'), 'connections' => [ 'pusher' => [ 'driver' => 'pusher', 'key' => env('PUSHER_APP_KEY'), 'secret' => env('PUSHER_APP_SECRET'), 'app_id' => env('PUSHER_APP_ID'), 'options' => [ 'cluster' => env('PUSHER_APP_CLUSTER'), ], ], ... ],
Теперь давайте добавим необходимые переменные среды в файл .env.
BROADCAST_DRIVER=pusher ... PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=
Нам нужно раскомментировать App \ Providers \ BroadcastServiceProvider.php в config/app.php
'providers' => [ ... App\Providers\BroadcastServiceProvider.php, ... ]
Теперь давайте посмотрим на файл, который мы только что раскомментировали. Здесь важен метод Broadcast :: routes (), который определяет маршруты для ответа на запросы авторизации канала. Он принимает $options
в качестве параметра так же, как Route::group()
принимает их, поэтому в моем случае, поскольку я использую токены JWT для аутентификации, мне нужно, чтобы запрос прошел через мое промежуточное ПО auth: api . Вызов метода routes
регистрирует broadcasting/auth
маршрут для обработки запросов авторизации.
class BroadcastServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Broadcast::routes(['middleware' => ['auth:api']]); require base_path('routes/channels.php'); } }
Упрощенная версия того, как работает вещание, заключается в том, что события проходят через каналы, и для получения событий мы должны подписаться на канал. Это то, что я делаю в своем приложении React, чтобы получать уведомления. Вы можете узнать больше о каналах в официальной документации Laravel. Я использую частные каналы, поэтому для получения событий требуется авторизация. Вместе с событиями мы можем передавать дополнительные данные.
Нам нужно определить нашу логику авторизации канала. В routes/channels.php
файле для нас уже есть пример канала. Я только немного изменил название канала.
Broadcast::channel('App.User.{id}', function ($user, $id) { return (int) $user->id === (int) $id; });
У каждого пользователя есть свой канал, и в этом примере только сам пользователь может подписаться на его канал.
Далее нам нужно настроить нашу модель пользователя. В частности, нам нужно сделать две вещи:
- Используйте свойство, подлежащее уведомлению
- Добавить
receivesBroadcastNotificationsOn
функцию. Здесь мы определяем канал, по которому начинают проходить уведомления пользователей. Убедитесь, что он соответствует каналу, указанному вchannels.php
.
use Illuminate\Notifications\Notifiable; /** * The channels the user receives notification broadcasts on. * * @return string */ public function receivesBroadcastNotificationsOn() { return 'App.User.' . $this->id; }
Создать класс (ы) уведомлений
Допустим, у нас есть система, в которой пользователи могут публиковать статьи и комментировать указанные статьи. Если кто-то добавит комментарий к моей статье, я хочу получить уведомление об этом. Итак, наш список TODO выглядит так:
- Создайте класс уведомлений
- Уведомить пользователя о добавлении комментария
В классе уведомлений мы должны определить несколько специальных методов вещания, таких как toBroadcast
method, где мы можем решить, какие данные передавать с уведомлением. Если вы используете Laravel 5.7, мы можем указать тип широковещательного события, и это сделает привязку к типам событий немного удобнее.
<?php namespace Guava\Communication\Notifications; use App\Models\Comment; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Notification; use Illuminate\Notifications\Messages\BroadcastMessage; class NewComment extends Notification implements ShouldQueue { use Queueable; /** @var Comment */ private $comment; public function __construct(Comment $comment) { $this->comment = $comment; } public function via($notifiable) { return ['database', 'broadcast']; } public function toArray($notifiable) { return [ 'post' => [ 'id' => $this->comment->post_id, ], 'author' => [ 'id' => $this->comment->user_id, 'first_name' => $this->comment->user->first_name, 'last_name' => $this->comment-user->last_name, ], 'comment' => [ 'id' => $this->comment->id, 'body' => $this->comment->body, 'commented_at' => $this->comment->commented_at, ], ]; } public function toBroadcast($notifiable) { return new BroadcastMessage($this->toArray($notifiable)); } public function broadcastType() { return 'new-comment'; } }
В моем случае я также хочу использовать уведомления базы данных и хочу, чтобы они были структурно такими же, как и BroadcastMessage
, поэтому я использую метод toArray
для определения возвращаемых данных. Если вы не хотите этого делать, просто удалите метод database
из via
и toArray
.
Я создал упрощенную конечную точку для хранения комментария и уведомления пользователя.
public function store(Post $post, StoreCommentRequest $request) { $comment = $post->addComment($request->all()); $post->author()->notify(NewComment($comment)); return new CommentResource($comment); }
Чтобы отладить и проверить, все ли работает, установитеBROADCAST_DRIVER=log
в файле .env и посмотрите, успешно ли добавление комментария добавляет информацию о транслируемом сообщении в журналы.
Добавить Pusher в React
npm install --save pusher-js laravel-echo
Я представлю упрощенную версию того, как инициализировать экземпляр Echo и как подписаться на каналы.
import Echo from 'laravel-echo'; const options = { broadcaster: 'pusher', key: config.pusher.key, cluster: config.pusher.cluster, forceTLS: config.pusher.tls, //authEndpoint is your apiUrl + /broadcasting/auth authEndpoint: config.pusher.authEndpoint, // As I'm using JWT tokens, I need to manually set up the headers. auth: { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json', }, }, }; const echo = new Echo(options); echo.private(`App.User.${userId}`).notification((data) => { console.log(data); });
Уведомления передаются по частному каналу. Laravel Echo - намного более удобный вариант по сравнению с пакетом PusherJS при использовании уведомлений Laravel для трансляции, потому что есть вспомогательная функция notification
, которая упрощает подписку на уведомления. В противном случае вам пришлось бы подписаться на событие под названием Illuminate\Notifications\Events\BroadcastNotificationCreated
и продолжить работу.
Надеюсь, это поможет вам, я провел почти весь день, начиная с нуля, без особых предварительных знаний о сокетах, широковещании и уведомлениях Laravel. Большую часть информации здесь можно найти в официальной документации Laravel о вещании уведомлений и вещании в целом.
Я полностью открыт для всех видов обратной связи и способов создания более чистого и эффективного кода. Я использую React всего несколько месяцев, так что мне нужно многому научиться.