Перевод статьи подготовлен специально для студентов курса «Framework Laravel».
Современный веб-пользователь ожидает быть информированным обо всем, что происходит в приложении. Вы бы не хотели быть тем веб-сайтом, у которого нет хотя бы раскрывающегося списка уведомлений, который теперь можно найти не только на всех сайтах социальных сетей, но и вообще повсюду в наши дни.
К счастью, с Laravel и Pusher реализация этого функционала довольно проста.
Для того, чтобы обеспечить положительный пользовательский опыт, уведомления должны отображаться в режиме реального времени. Одним из подходов является регулярная отправка AJAX-запроса на сервер и получение новейших уведомлений, если таковые существуют.
Лучшим подходом является использование возможностей WebSockets и получение уведомлений в момент их отправки. Это именно то, что мы собираемся реализовать в этой статье.
Pusher — это веб-сервис для интеграции двунаправленной функциональности в реальном времени через WebSockets в веб и мобильные приложения.
У него очень простой API, но мы собираемся сделать его использование еще проще с Laravel Broadcasting и Laravel Echo.
В этой статье мы собираемся добавить уведомления в реальном времени в уже существующий блог.
Сначала мы клонируем простой блог Laravel:
Затем мы создадим базу данных MySQL и настроим переменные среды, чтобы предоставить приложению доступ к базе данных.
Давайте скопируем
Теперь давайте установим зависимости проекта с помощью
И запустим команду миграции и заполнения, чтобы заполнить базу данных какими-нибудь данными:
Если вы запустите приложение и зайдите в
Проверьте приложение, зарегистрируйте пользователя и создайте несколько сообщений. Это очень простое приложение, но оно отлично подходит для демонстрации.
Мы хотели бы дать пользователям возможность подписываться друг на друга, поэтому мы должны создать отношение «многие ко многим» между пользователями, чтобы это реализовать.
Давайте создадим сводную таблицу, которая связывает пользователей с пользователями. Сделаем новую миграцию
Нам нужно добавить несколько полей к этой миграции:
Обновите миграцию следующим образом:
Теперь перейдем к созданию таблицы:
Давайте добавим методы отношений в модель
Теперь, когда модель
Нам понадобятся некоторые вспомогательные функции, позволяющие пользователю подписываться на других пользователей —
Отлично. После подготовки модели нужно составить список пользователей.
Давайте начнем с определения необходимых маршрутов
Затем пришло время создать новый контроллер для пользователей:
Мы добавим к нему метод
Метод нуждается в представлении. Давайте создадим представление
Теперь вы можете посетить страницу
В
С этим функционалом мы закончили. Теперь мы можем подписываться на пользователей и отписываться от них на странице
Laravel предоставляет API для отправки уведомлений по нескольким каналам. Электронная почта, SMS, веб-уведомления и любые другие типы уведомлений могут быть отправлены с помощью класса Notification.
У нас будет два типа уведомлений:
Используя artisan-команды, мы можем сгенерировать миграцию для уведомлений:
Давайте выполним миграцию и создадим эту таблицу.
Мы начнем с уведомлений о подписке. Давайте выполним эту команду для создания класса уведомлений:
Затем мы модифицируем файл класса уведомлений, который мы только что создали:
С помощью этих нескольких строк кода мы уже можем достичь многого. Сначала мы требуем, чтобы экземпляр
Используя метод
И, наконец, благодаря реализации
Давайте реализуем уведомление о подписке на пользователя.
Мы можем вызвать метод notify для модели User, потому что она уже использует черту Notifiable.
Любая модель, которую вы хотите уведомить, должна использовать ее для получения доступа к методу notify.
Отмечаем уведомление как прочитанное
Уведомления будут содержать некоторую информацию и ссылку на ресурс. Например: когда пользователь получает уведомление о новом сообщении, уведомление должно содержать информативный текст, перенаправлять пользователя на сообщение при нажатии и помечаться как прочитанное.
Мы собираемся создать прослойку, которая будет проверять, есть ли в запросе вхождение
Давайте сделаем эту прослойку с помощью следующей команды:
Затем давайте поместим этот код в метод
Для того, чтобы наша прослойка выполнялась для каждого запроса, мы добавим ее в
После этого давайте займемся отображением уведомлений.
Мы должны показать список уведомлений, используя AJAX, а затем обновить его в режиме реального времени с помощью Pusher. Во-первых, давайте добавим метод
Этот код вернет последние 5 непрочитанных уведомлений. Нам просто нужно добавить маршрут, чтобы сделать его доступным.
Теперь добавим выпадающий список для уведомлений в шапке.
Мы также добавили глобальную переменную
Мы собираемся использовать Laravel Mix для компиляции JavaScript и SASS. Во-первых, нам нужно установить npm-пакеты.
Теперь давайте добавим этот код в
Это всего лишь инициализация. Мы собираемся использовать notifications для хранения всех объектов уведомлений, независимо от того, извлекаются ли они через AJAX или Pusher.
Как вы, наверное, уже догадались,
Теперь давайте получим (“GET”) уведомления через AJAX.
Благодаря этому коду мы получаем последние уведомления от нашего API и помещаем их в раскрывающийся список.
Внутри
Нам нужно еще несколько функций, чтобы закончить работу.
Эта функция создает строку всех уведомлений и помещает ее в раскрывающийся список.
Если не было получено ни одного уведомления, отображается просто «Нет уведомлений».
Она также добавляет класс к выпадающей кнопке, которая просто изменит свой цвет при наличии уведомлений. Немного напоминает уведомления на Github.
Наконец, некоторые вспомогательные функции для создания строк уведомлений.
Теперь мы просто добавим это в наш файл
Давайте скомпилируем ассеты:
Теперь если вы попытаетесь подписаться на пользователя, он получит уведомление. Когда он кликнет по нему, он будет перенаправлен в
Мы собираемся уведомлять подписчиков, когда пользователь публикует новый пост.
Начнем с создания класса уведомлений.
Давайте модифицируем сгенерированный класс следующим образом:
Далее нам нужно отправить уведомление. Есть несколько способов сделать это.
Мне нравится использовать наблюдатели Eloquent.
Давайте создадим наблюдателя за Post и будем слушать его события. Мы создадим новый класс:
Затем зарегистрируем наблюдателя в
Теперь нам просто нужно отформатировать сообщение для отображения в JS:
И вуаля! Пользователи получают уведомления о подписках и новых постах! Попробуйте сами!
Пришло время использовать Pusher для получения уведомлений в режиме реального времени через веб-сокеты.
Зарегистрируйте бесплатную учетную запись Pusher на pusher.com и создайте новое приложение.
Задайте параметры своей учетной записи в файле конфигурации
Затем мы зарегистрируем
Теперь мы должны установить PHP SDK и Laravel Echo от Pusher:
Нам нужно настроить данные уведомлений для трансляции. Давайте модифицируем уведомление
И
Последнее, что нам нужно сделать, это обновить наш JS. Откройте
И на этом все. Уведомления добавляются в режиме реального времени. Теперь вы можете поиграть с приложением и посмотреть, как обновляются уведомления.
У Pusher очень удобный API, который делает реализацию событий в реальном времени невероятно простой. В сочетании с уведомлениями Laravel мы можем отправлять уведомления по нескольким каналам (электронная почта, SMS, Slack и т. д.) из одного места. В этом руководстве мы добавили функциональные возможности для отслеживания активности пользователей в простой блог и усовершенствовали его с помощью вышеупомянутых инструментов, чтобы получить некоторый плавный функционал в реальном времени.
У Pusher и Laravel есть гораздо больше уведомлений: в тандеме сервисы позволяют отправлять pub/sub-сообщения в режиме реального времени на браузеры, мобильные телефоны и IOT-устройства. Существует также API для получения online/offline статуса пользователей.
Пожалуйста, ознакомьтесь с их документацией (Pusher docs, Pusher tutorials, Laravel docs), чтобы узнать более подробную информацию о их использовании и истинном потенциале.
Если у вас есть какие-либо комментарии, вопросы или рекомендации, не стесняйтесь делиться ими в комментариях ниже!
Узнать подробнее о курсе.
Современный веб-пользователь ожидает быть информированным обо всем, что происходит в приложении. Вы бы не хотели быть тем веб-сайтом, у которого нет хотя бы раскрывающегося списка уведомлений, который теперь можно найти не только на всех сайтах социальных сетей, но и вообще повсюду в наши дни.
К счастью, с Laravel и Pusher реализация этого функционала довольно проста.
Уведомления в реальном времени
Для того, чтобы обеспечить положительный пользовательский опыт, уведомления должны отображаться в режиме реального времени. Одним из подходов является регулярная отправка AJAX-запроса на сервер и получение новейших уведомлений, если таковые существуют.
Лучшим подходом является использование возможностей WebSockets и получение уведомлений в момент их отправки. Это именно то, что мы собираемся реализовать в этой статье.
Pusher
Pusher — это веб-сервис для интеграции двунаправленной функциональности в реальном времени через WebSockets в веб и мобильные приложения.
У него очень простой API, но мы собираемся сделать его использование еще проще с Laravel Broadcasting и Laravel Echo.
В этой статье мы собираемся добавить уведомления в реальном времени в уже существующий блог.
Проект
Инициализация
Сначала мы клонируем простой блог Laravel:
git clone https://github.com/marslan-ali/laravel-blog
Затем мы создадим базу данных MySQL и настроим переменные среды, чтобы предоставить приложению доступ к базе данных.
Давайте скопируем
env.example
в .env
и обновим переменные, связанные с базой данных.cp .env.example .envDB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
Теперь давайте установим зависимости проекта с помощью
composer install
И запустим команду миграции и заполнения, чтобы заполнить базу данных какими-нибудь данными:
php artisan migrate --seed
Если вы запустите приложение и зайдите в
/posts
, вы сможете увидеть список сгенерированных постов.Проверьте приложение, зарегистрируйте пользователя и создайте несколько сообщений. Это очень простое приложение, но оно отлично подходит для демонстрации.
Подписка на пользователей
Мы хотели бы дать пользователям возможность подписываться друг на друга, поэтому мы должны создать отношение «многие ко многим» между пользователями, чтобы это реализовать.
Давайте создадим сводную таблицу, которая связывает пользователей с пользователями. Сделаем новую миграцию
followers
:php artisan make:migration create_followers_table --create=followers
Нам нужно добавить несколько полей к этой миграции:
user_id
для представления пользователя, который подписан, и поле follows_id
для представления пользователя, на которого подписались.Обновите миграцию следующим образом:
public function up()
{
Schema::create('followers', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->integer('follows_id')->index();
$table->timestamps();
});
}
Теперь перейдем к созданию таблицы:
php artisan migrate
Давайте добавим методы отношений в модель
User
.// ...
class extends Authenticatable
{
// ...
public function followers()
{
return $this->belongsToMany(self::class, 'followers', 'follows_id', 'user_id')
->withTimestamps();
}
public function follows()
{
return $this->belongsToMany(self::class, 'followers', 'user_id', 'follows_id')
->withTimestamps();
}
}
Теперь, когда модель
User
имеет необходимые отношения, followers
возвращает всех подписчиков пользователя, а follows
возвращает всех, на кого подписан сам пользователь.Нам понадобятся некоторые вспомогательные функции, позволяющие пользователю подписываться на других пользователей —
follow
, и проверять, подписан ли пользователь на какого-нибудь конкретного пользователя — isFollowing
.// ...
class extends Authenticatable
{
// ...
public function follow($userId)
{
$this->follows()->attach($userId);
return $this;
}
public function unfollow($userId)
{
$this->follows()->detach($userId);
return $this;
}
public function isFollowing($userId)
{
return (boolean) $this->follows()->where('follows_id', $userId)->first(['id']);
}
}
Отлично. После подготовки модели нужно составить список пользователей.
Список пользователей
Давайте начнем с определения необходимых маршрутов
/...
Route::group(['middleware' => 'auth'], function () {
Route::get('users', 'UsersController@index')->name('users');
Route::post('users/{user}/follow', 'UsersController@follow')->name('follow');
Route::delete('users/{user}/unfollow', 'UsersController@unfollow')->name('unfollow');
});
Затем пришло время создать новый контроллер для пользователей:
php artisan make:controller UsersController
Мы добавим к нему метод
index
:// ...
use App\User;
class UsersController extends Controller
{
//..
public function index()
{
$users = User::where('id', '!=', auth()->user()->id)->get();
return view('users.index', compact('users'));
}
}
Метод нуждается в представлении. Давайте создадим представление
users.index
и поместим в него следующую разметку:@extends('layouts.app')
@section('content')
<div class="container">
<div class="col-sm-offset-2 col-sm-8">
<!-- Following -->
<div class="panel panel-default">
<div class="panel-heading">
All Users
</div>
<div class="panel-body">
<table class="table table-striped task-table">
<thead>
<th>User</th>
<th> </th>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td clphpass="table-text"><div>{{ $user->name }}</div></td>
@if (auth()->user()->isFollowing($user->id))
<td>
<form action="{{route('unfollow', ['id' => $user->id])}}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit" id="delete-follow-{{ $user->id }}" class="btn btn-danger">
<i class="fa fa-btn fa-trash"></i>Unfollow
</button>
</form>
</td>
@else
<td>
<form action="{{route('follow', ['id' => $user->id])}}" method="POST">
{{ csrf_field() }}
<button type="submit" id="follow-user-{{ $user->id }}" class="btn btn-success">
<i class="fa fa-btn fa-user"></i>Follow
</button>
</form>
</td>
@endif
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection
Теперь вы можете посетить страницу
/users
, чтобы увидеть список пользователей.Follow и Unfollow
В
UsersController
отсутствуют методы follow
и unfollow
. Давайте реализуем их, чтобы завершить эту часть.//...
class UsersController extends Controller
{
//...
public function follow(User $user)
{
$follower = auth()->user();
if ($follower->id == $user->id) {
return back()->withError("You can't follow yourself");
}
if(!$follower->isFollowing($user->id)) {
$follower->follow($user->id);
// отправка уведомления
$user->notify(new UserFollowed($follower));
return back()->withSuccess("You are now friends with {$user->name}");
}
return back()->withError("You are already following {$user->name}");
}
public function unfollow(User $user)
{
$follower = auth()->user();
if($follower->isFollowing($user->id)) {
$follower->unfollow($user->id);
return back()->withSuccess("You are no longer friends with {$user->name}");
}
return back()->withError("You are not following {$user->name}");
}
}
С этим функционалом мы закончили. Теперь мы можем подписываться на пользователей и отписываться от них на странице
/users
.Уведомления
Laravel предоставляет API для отправки уведомлений по нескольким каналам. Электронная почта, SMS, веб-уведомления и любые другие типы уведомлений могут быть отправлены с помощью класса Notification.
У нас будет два типа уведомлений:
- Уведомление о подписке: отправляется пользователю, когда на него подписывается другой пользователь
- Уведомление о посте: отправляется подписчикам данного пользователя при публикации нового поста.
Уведомление о подписке
Используя artisan-команды, мы можем сгенерировать миграцию для уведомлений:
php artisan notifications:table
Давайте выполним миграцию и создадим эту таблицу.
php artisan migrate
Мы начнем с уведомлений о подписке. Давайте выполним эту команду для создания класса уведомлений:
php artisan make:notification UserFollowed
Затем мы модифицируем файл класса уведомлений, который мы только что создали:
class UserFollowed extends Notification implements ShouldQueue
{
use Queueable;
protected $follower;
public function __construct(User $follower)
{
$this->follower = $follower;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'follower_id' => $this->follower->id,
'follower_name' => $this->follower->name,
];
}
}
С помощью этих нескольких строк кода мы уже можем достичь многого. Сначала мы требуем, чтобы экземпляр
$follower
был внедрен при создании этого уведомления.Используя метод
via
, мы говорим Laravel отправить это уведомление через канал database
. Когда Laravel сталкивается с этим, он создает новую запись в таблице уведомлений.user_id
и type
уведомления устанавливаются автоматически, плюс мы можем расширить уведомление дополнительными данными. Вот для чего предназначен toDatabase
. Возвращаемый массив будет добавлен в поле data
уведомления.И, наконец, благодаря реализации
ShouldQueue
, Laravel автоматически поместит это уведомление в очередь, которая будет выполняться в фоновом режиме, что ускорит ответ. Это имеет смысл, потому что мы будем добавлять HTTP-вызовы, когда будем использовать Pusher позже.Давайте реализуем уведомление о подписке на пользователя.
// ...
use App\Notifications\UserFollowed;
class UsersController extends Controller
{
// ...
public function follow(User $user)
{
$follower = auth()->user();
if ( ! $follower->isFollowing($user->id)) {
$follower->follow($user->id);
// добавить это, чтобы отправить уведомление
$user->notify(new UserFollowed($follower));
return back()->withSuccess("You are now friends with {$user->name}");
}
return back()->withSuccess("You are already following {$user->name}");
}
//...
}
Мы можем вызвать метод notify для модели User, потому что она уже использует черту Notifiable.
Любая модель, которую вы хотите уведомить, должна использовать ее для получения доступа к методу notify.
Отмечаем уведомление как прочитанное
Уведомления будут содержать некоторую информацию и ссылку на ресурс. Например: когда пользователь получает уведомление о новом сообщении, уведомление должно содержать информативный текст, перенаправлять пользователя на сообщение при нажатии и помечаться как прочитанное.
Мы собираемся создать прослойку, которая будет проверять, есть ли в запросе вхождение
?read=notification_id
и помечает его как прочитанное.Давайте сделаем эту прослойку с помощью следующей команды:
php artisan make:middleware MarkNotificationAsRead
Затем давайте поместим этот код в метод
handle
прослойки:class MarkNotificationAsRead
{
public function handle($request, Closure $next)
{
if($request->has('read')) {
$notification = $request->user()->notifications()->where('id', $request->read)->first();
if($notification) {
$notification->markAsRead();
}
}
return $next($request);
}
}
Для того, чтобы наша прослойка выполнялась для каждого запроса, мы добавим ее в
$middlewareGroups
.//...
class Kernel extends HttpKernel
{
//...
protected $middlewareGroups = [
'web' => [
//...
\App\Http\Middleware\MarkNotificationAsRead::class,
],
// ...
];
//...
}
После этого давайте займемся отображением уведомлений.
Отображение уведомлений
Мы должны показать список уведомлений, используя AJAX, а затем обновить его в режиме реального времени с помощью Pusher. Во-первых, давайте добавим метод
notifications
в контроллер:// ...
class UsersController extends Controller
{
// ...
public function notifications()
{
return auth()->user()->unreadNotifications()->limit(5)->get()->toArray();
}
}
Этот код вернет последние 5 непрочитанных уведомлений. Нам просто нужно добавить маршрут, чтобы сделать его доступным.
//...
Route::group([ 'middleware' => 'auth' ], function () {
// ...
Route::get('/notifications', 'UsersController@notifications');
});
Теперь добавим выпадающий список для уведомлений в шапке.
<head>
<!-- // ... // -->
<!-- Scripts -->
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
<!-- Это делает id текущего пользователя доступным в JavaScript -->
@if(!auth()->guest())
<script>
window.Laravel.userId = <?php echo auth()->user()->id; ?>
</script>
@endif
</head>
<body>
<!-- // ... // -->
@if (Auth::guest())
<li><a href="{{ url('/login') }}">Login</a></li>
<li><a href="{{ url('/register') }}">Register</a></li>
@else
<!-- // add this dropdown // -->
<li class="dropdown">
<a class="dropdown-toggle" id="notifications" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span class="glyphicon glyphicon-user"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="notificationsMenu" id="notificationsMenu">
<li class="dropdown-header">No notifications</li>
</ul>
</li>
<!-- // ... // -->
Мы также добавили глобальную переменную
window.Laravel.userId
в скрипт, чтобы получить ID текущего пользователя.JavaScript и SASS
Мы собираемся использовать Laravel Mix для компиляции JavaScript и SASS. Во-первых, нам нужно установить npm-пакеты.
npm install
Теперь давайте добавим этот код в
app.js
:window._ = require('lodash');
window.$ = window.jQuery = require('jquery');
require('bootstrap-sass');
var notifications = [];
const NOTIFICATION_TYPES = {
follow: 'App\\Notifications\\UserFollowed'
};
Это всего лишь инициализация. Мы собираемся использовать notifications для хранения всех объектов уведомлений, независимо от того, извлекаются ли они через AJAX или Pusher.
Как вы, наверное, уже догадались,
NOTIFICATION_TYPES
содержит типы уведомлений.Теперь давайте получим (“GET”) уведомления через AJAX.
//...
$(document).ready(function() {
// проверить, есть ли вошедший в систему пользователь
if(Laravel.userId) {
$.get('/notifications', function (data) {
addNotifications(data, "#notifications");
});
}
});
function addNotifications(newNotifications, target) {
notifications = _.concat(notifications, newNotifications);
// показываем только последние 5 уведомлений
notifications.slice(0, 5);
showNotifications(notifications, target);
}
Благодаря этому коду мы получаем последние уведомления от нашего API и помещаем их в раскрывающийся список.
Внутри
addNotifications
мы объединяем имеющиеся уведомления с новыми, используя Lodash, и берем только последние 5, которые и будут показаны.Нам нужно еще несколько функций, чтобы закончить работу.
//...
function showNotifications(notifications, target) {
if(notifications.length) {
var htmlElements = notifications.map(function (notification) {
return makeNotification(notification);
});
$(target + 'Menu').html(htmlElements.join(''));
$(target).addClass('has-notifications')
} else {
$(target + 'Menu').html('<li class="dropdown-header">No notifications</li>');
$(target).removeClass('has-notifications');
}
}
Эта функция создает строку всех уведомлений и помещает ее в раскрывающийся список.
Если не было получено ни одного уведомления, отображается просто «Нет уведомлений».
Она также добавляет класс к выпадающей кнопке, которая просто изменит свой цвет при наличии уведомлений. Немного напоминает уведомления на Github.
Наконец, некоторые вспомогательные функции для создания строк уведомлений.
//...
// Сделать строку уведомления
function makeNotification(notification) {
var to = routeNotification(notification);
var notificationText = makeNotificationText(notification);
return '<li><a href="' + to + '">' + notificationText + '</a></li>';
}
// получить маршрут уведомления в зависимости от его типа
function routeNotification(notification) {
var to = '?read=' + notification.id;
if(notification.type === NOTIFICATION_TYPES.follow) {
to = 'users' + to;
}
return '/' + to;
}
// получить текст уведомления в зависимости от его типа
function makeNotificationText(notification) {
var text = '';
if(notification.type === NOTIFICATION_TYPES.follow) {
const name = notification.data.follower_name;
text += '<strong>' + name + '</strong> followed you';
}
return text;
}
Теперь мы просто добавим это в наш файл
app.scss
://...
#notifications.has-notifications {
color: #bf5329
}
Давайте скомпилируем ассеты:
npm run dev
Теперь если вы попытаетесь подписаться на пользователя, он получит уведомление. Когда он кликнет по нему, он будет перенаправлен в
/users
, а само уведомление исчезает.Уведомление о новом посте
Мы собираемся уведомлять подписчиков, когда пользователь публикует новый пост.
Начнем с создания класса уведомлений.
php artisan make:notification NewPost
Давайте модифицируем сгенерированный класс следующим образом:
// ..
use App\Post;
use App\User;
class NewArticle extends Notification implements ShouldQueue
{
// ..
protected $following;
protected $post;
public function __construct(User $following, Post $post)
{
$this->following = $following;
$this->post = $post;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'following_id' => $this->following->id,
'following_name' => $this->following->name,
'post_id' => $this->post->id,
];
}
}
Далее нам нужно отправить уведомление. Есть несколько способов сделать это.
Мне нравится использовать наблюдатели Eloquent.
Давайте создадим наблюдателя за Post и будем слушать его события. Мы создадим новый класс:
app/Observers/PostObserver.php
namespace App\Observers;
use App\Notifications\NewPost;
use App\Post;
class PostObserver
{
public function created(Post $post)
{
$user = $post->user;
foreach ($user->followers as $follower) {
$follower->notify(new NewPost($user, $post));
}
}
}
Затем зарегистрируем наблюдателя в
AppServiceProvider
://...
use App\Observers\PostObserver;
use App\Post;
class AppServiceProvider extends ServiceProvider
{
//...
public function boot()
{
Post::observe(PostObserver::class);
}
//...
}
Теперь нам просто нужно отформатировать сообщение для отображения в JS:
// ...
const NOTIFICATION_TYPES = {
follow: 'App\\Notifications\\UserFollowed',
newPost: 'App\\Notifications\\NewPost'
};
//...
function routeNotification(notification) {
var to = `?read=${notification.id}`;
if(notification.type === NOTIFICATION_TYPES.follow) {
to = 'users' + to;
} else if(notification.type === NOTIFICATION_TYPES.newPost) {
const postId = notification.data.post_id;
to = `posts/${postId}` + to;
}
return '/' + to;
}
function makeNotificationText(notification) {
var text = '';
if(notification.type === NOTIFICATION_TYPES.follow) {
const name = notification.data.follower_name;
text += `<strong>${name}</strong> followed you`;
} else if(notification.type === NOTIFICATION_TYPES.newPost) {
const name = notification.data.following_name;
text += `<strong>${name}</strong> published a post`;
}
return text;
}
И вуаля! Пользователи получают уведомления о подписках и новых постах! Попробуйте сами!
Выходим в режим реального времени с Pusher
Пришло время использовать Pusher для получения уведомлений в режиме реального времени через веб-сокеты.
Зарегистрируйте бесплатную учетную запись Pusher на pusher.com и создайте новое приложение.
...
BROADCAST_DRIVER=pusher
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
Задайте параметры своей учетной записи в файле конфигурации
broadcasting
://...
'connections' => [
'pusher' => [
//...
'options' => [
'cluster' => 'eu',
'encrypted' => true
],
],
//...
Затем мы зарегистрируем
App\Providers\BroadcastServiceProvider
в массиве providers
.// ...
'providers' => [
// ...
App\Providers\BroadcastServiceProvider
//...
],
//...
Теперь мы должны установить PHP SDK и Laravel Echo от Pusher:
composer require pusher/pusher-php-server
npm install --save laravel-echo pusher-js
Нам нужно настроить данные уведомлений для трансляции. Давайте модифицируем уведомление
UserFollowed
://...
class UserFollowed extends Notification implements ShouldQueue
{
// ..
public function via($notifiable)
{
return ['database', 'broadcast'];
}
//...
public function toArray($notifiable)
{
return [
'id' => $this->id,
'read_at' => null,
'data' => [
'follower_id' => $this->follower->id,
'follower_name' => $this->follower->name,
],
];
}
}
И
NewPost
://...
class NewPost extends Notification implements ShouldQueue
{
//...
public function via($notifiable)
{
return ['database', 'broadcast'];
}
//...
public function toArray($notifiable)
{
return [
'id' => $this->id,
'read_at' => null,
'data' => [
'following_id' => $this->following->id,
'following_name' => $this->following->name,
'post_id' => $this->post->id,
],
];
}
}
Последнее, что нам нужно сделать, это обновить наш JS. Откройте
app.js
и добавьте следующий код// ...
window.Pusher = require('pusher-js');
import Echo from "laravel-echo";
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
cluster: 'eu',
encrypted: true
});
var notifications = [];
//...
$(document).ready(function() {
if(Laravel.userId) {
//...
window.Echo.private(`App.User.${Laravel.userId}`)
.notification((notification) => {
addNotifications([notification], '#notifications');
});
}
});
И на этом все. Уведомления добавляются в режиме реального времени. Теперь вы можете поиграть с приложением и посмотреть, как обновляются уведомления.
Вывод
У Pusher очень удобный API, который делает реализацию событий в реальном времени невероятно простой. В сочетании с уведомлениями Laravel мы можем отправлять уведомления по нескольким каналам (электронная почта, SMS, Slack и т. д.) из одного места. В этом руководстве мы добавили функциональные возможности для отслеживания активности пользователей в простой блог и усовершенствовали его с помощью вышеупомянутых инструментов, чтобы получить некоторый плавный функционал в реальном времени.
У Pusher и Laravel есть гораздо больше уведомлений: в тандеме сервисы позволяют отправлять pub/sub-сообщения в режиме реального времени на браузеры, мобильные телефоны и IOT-устройства. Существует также API для получения online/offline статуса пользователей.
Пожалуйста, ознакомьтесь с их документацией (Pusher docs, Pusher tutorials, Laravel docs), чтобы узнать более подробную информацию о их использовании и истинном потенциале.
Если у вас есть какие-либо комментарии, вопросы или рекомендации, не стесняйтесь делиться ими в комментариях ниже!
Узнать подробнее о курсе.
mukoladerevlo
спасибо за статью. недавно делал чат на вебсокетах перечитал тону информации. если нет желания использовать сервис pusher, есть бесплатная альтернатива, в виде beyondcode/laravel-websockets. все также как по статье, только вы будете использовать свой локальный вебсокет сервер вместо сервера пушера. Библиотеки на клиенте теже. pusher.js и echo. wss проще организовать на 443 порту, через proxypass(по сути переадресация). с letsencrypt на 6001 у меня не завелось
1c80
Спасибо, тоже не хотелось бы использовать чужой сервис, завтра он свернётся и все переделывать надо будет за свой счёт, в наше время стрёмно на кого-то полагаться.
серт не заработал из-за настроек думаю, с ними всегда гимор, по идее скоро ковырять тоже буду, как найду напишу.
Dinver
Попробуйте Centrifugo, делал на нем мультимессенджер как раз в связке с Laravel. Он удобный, простой в освоении, жрет мало и работает отлично. Но конечно это не библиотека, а полноценный сервер.
1c80
Да, спасибо, оно по проще вроде и докер есть официальный, что для такого функционала самое оно.