В этой статье, я расскажу как установить и запустить Laravel Echo Server, и создать приложение работающее в реальном времени.
Для работы нам понадобиться:
Как установить и настроить Redis, можно прочитать в моей заметке Установка и настройка Redis на Debian 9.
И так, все исходные данны есть, можно начинать!
Установим laravel-echo-server через npm глобально:
npm install -g laravel-echo-server
Теперь перейдём в директорию нашего проекта и выполним инициализацию Laravel Echo Server:
laravel-echo-server init
Данная команда поможет создать файл конфигурации laravel-echo-server.json, который появиться в корневой директории вашего проекта. Во время процесса инициализации вам надо будет ответить на несколько вопросов, например для начала, лучше выбрать dev режим, а в качестве базы данных обязательно указать redis. Остальные вопросы разбирать не будем, тк все в принципе понятно. Если что-то не понятно - задавайте вопросы в комментариях.
Теперь, если все хорошо, запускаем:
laravel-echo-server start
Если запуск прошёл успешно, то мы увидем подобное сообщение:
А если не успешно? ВНИМАНИЕ! Если вы настроили Redis c использованием пароля (как я рекомендовал в своей статье), то вы получите ошибку:
[ioredis] Unhandled error event: ReplyError: NOAUTH Authentication required.
Это значит, что мы не настроили параметры подключения в файле конфига laravel-echo-server.json. Так что открываем файл конфига, и дополняем его параметрами подключения к Redis:
"databaseConfig": {
"redis": {
"port":"6379",
"host":"127.0.0.1",
"password":"07d3b02346d294d12e3582dab8b9ed329ab316ed22a19297537377794833defc"
}
},
Сохраняем конфиг и снова запускаем Laravel Echo Server:
laravel-echo-server start
Теперь все должно быть хорошо, и мы увидим сообщение как на изображении выше.
Откройте ваш config/app.php файл и раскомментируйте BroadcastServiceProvider в массиве provider:
App\Providers\BroadcastServiceProvider::class,
Этот провайдер включит широковещательные маршруты.
Откройте .env файл и установите redis в качестве BROADCAST_DRIVER и QUEUE_DRIVER (для работы очередей в laravel мы тоже можем использовать redis).
В .env нам так же надо задать параметры подключения к Redis:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=07d3b02346d294d12e3582dab8b9ed329ab316ed22a19297537377794833defc
REDIS_PORT=6379
Теперь нам нужно установить клиент socket.io и пакет laravel-echo, вы можете сделать это, выполнив:
npm install --save socket.io-client
npm install --save laravel-echo
Перед запуском возможно понадобиться выполнить
npm install
для установки зависимостей.
Все готово! Можно радостно хлопать в ладоши или что вы там обычно делаете когда все получается!
И так, все настроено и готово к работе! Ниже, я покажу как реализовать систему увидомлений, на примере уведомления о новом комментарии в моей блоге. Если у вас недостаточно знаний о событиях и их транслировании в Laravel, настоятельно рекомендую изучить официальную документацию.
Первым делом создадим новое событие выполнив команду:
php artisan make: event CommentAdd
Важно помнить, что наш класс события должен реализовывать интерфейс ShouldBroadcast
.
Приведу пример моего класса целиком:
<?php
namespace App\Events;
use App\Comment;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class CommentAdd implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $comment;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Comment $comment)
{
$this->comment = $comment;
}
/**
* The event's broadcast name.
*
* @return string
*/
public function broadcastAs()
{
return 'comment.add';
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('notification.admin');
}
}
Все публичные свойства класса, как в нашем случае свойство $comment, будут сериализованы и отправлены как данные для вещания. Обогатить транслируемые данные можно в конструкторе нашего класса.
В методе broadcastAs()
указываем имя нашего события. Реализовывать этот метод не обязательно, тк по умолчанию, в качестве имени события, Laravel будет использовать имя нашего класса - CommentAdd.
Метод broadcastOn()
должен возвращать экземпляр канала, с заданным названием канала.
Существует ещё такой метод как:
public function broadcastWith()
{
return [
'user' => 'test user'
];
}
Данный метод должен возвращать массив данных, которые будут транслироваться в качестве так называемой полезной нагрузки.
Теперь нам надо вызвать наше событие. У меня для модели комментариев реализован слушатель событий, подробнее можно почитать в официальной документации.
Ниже пример реализации вызова события CommentAdd, через слушатель событий модели комментариев:
<?php
namespace App\Observers;
use ...
class CommentObserver
{
/**
* Handle the comment "created" event.
*
* @param \App\Comment $comment
* @return void
*/
public function created(Comment $comment)
{
event(new CommentAdd($comment));
}
Тут нас интересует строчка event(new CommentAdd($comment));
именно она отвечает за вызов события CommentAdd, к конструктор которого мы передаём объект комментария. В своём примере вы можете использовать метод event()
где хотите. Для примера можно создать маршрут с вызовом события:
Route::get('test-broadcast', function () {
event(new \App\Events\ExampleEvent(['foo' => 'bar']));
});
Теперь запустим слушатель очереди с помощью artisan команды:
php artisan queue: listen --tries = 1
И вызовем наше событие с помощью метода event()
как показано на примере выше. Если все прошло успешно, в консоли мы увидим примерно следующее:
master@s777:~/www/laravel-test.local/site$ php artisan queue:listen --tries=1
[2020-04-18 17:40:40][XUj7c87GIcpoKn6mQNz0xgDCfQGzH4ZC] Processing: App\Events\CommentAdd
[2020-04-18 17:40:40][XUj7c87GIcpoKn6mQNz0xgDCfQGzH4ZC] Processed: App\Events\CommentAdd
Это значит, что наше событие успешно отправилось в очередь.
Если ваш laravel echo server запущен в dev режиме, то в консоле можно будет увидеть основную информацию о том что происходит на сервере. В данном случае нас интересуют следующие строчки:
Channel: notification.admin
Event: comment.add
Это значит, что все настроили верно. Осталось дело за слушателями этих событий на клиенте.
Заключительный этап - реализация слушателей событий на клиенте.
Возможно, вы не знакомы со сборщиками фронтенда в Laravel. В этом случае необходимо ознакомиться с официальном документацией.
Откроем для редактирования файл resources/assets/js/bootstrap.js (в версиях Laravel 5.7 и выше этот файл можно найти по пути resources/js/bootstrap.js).
Запишем базовый код для работы с Echo server:
import Echo from "laravel-echo";
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
Далее создаём js скрипт с кодом самого слушателя:
window.Echo.channel('notification.admin')
.listen('.comment.add', (e) => {
console.log(e);
});
Данный код говорит о том, что мы подписываемся на канал notification.admin и слушаем событие comment.add, именно такие названия канала и события мы задали в php классе CommentAdd в примерах выше.
Хочу обратить внимание, что в методе broadcastAs класса события CommentAdd мы указали название события без точки в начале "comment.add", а в js коде уже с точкой ".comment.add". Это не ошибка.
Подключите наши js скрипты на любую страницу вашего сайта, например на главную. Теперь повторите вызов события с помощью метода event() как показано на примерах выше.
В консоли браузера (на страницах где подключены наши js скрипты) вы должны увидеть данные которые пришли из события, например как у меня:
Здорово, не правда ли?:)
Кстати, js код слушателя можно немного усовершенствовать, для прослушивания нескольких событий, например:
const channel = window.Echo.channel('notification.admin');
const eventsTolisten = [
'.comment.add',
'.comment.delete',
];
eventsTolisten.forEach(event => {
channel.listen(event, e => {
console.log(event+':');
console.log(e);
})
});
На этом всё! Надеюсь всё понятно. Если остались вопросы или есть предложения и пожелания - пишите комментарии.
{{ item.text }}