Advertisement
  1. Code
  2. Laravel 5
Code

Как работает Laravel Broadcasting

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Сегодня мы рассмотрим концепцию вещания в веб-среде Laravel. Она позволяет отправлять уведомления стороне клиента, когда что-то происходит на стороне сервера. В этой статье мы собираемся использовать стороннюю библиотеку Pusher для отправки уведомлений на стороне клиента.

Если вы когда-либо хотели отправлять уведомления с сервера клиенту, когда что-то происходит на сервере в Laravel, вам определенно нужна фича broadcasting.

Например, предположим, что вы внедрили приложение обмена сообщениями, которое позволяет пользователям вашей системы отправлять сообщения друг другу. Теперь, когда пользователь A отправляет сообщение пользователю B, вы хотите уведомить пользователя B в режиме реального времени. Вы можете отобразить всплывающее окно или окно предупреждения, которое информирует пользователя B о новом сообщении!

Это идеальный use-case, чтобы рассмотреть концепцию трансляции в Laravel, и это то, что мы будем реализовывать в этой статье.

Если вам интересно, как сервер может отправлять уведомления клиенту, для его выполнения используются сокеты под капотом. Давайте рассмотрим основной поток сокетов, прежде чем погрузиться в реальную реализацию.

  • Во-первых, вам нужен сервер, поддерживающий протокол веб-сокетов и позволяющий клиенту устанавливать соединение с веб-сокетом.
  • Вы можете реализовать свой собственный сервер или использовать стороннюю службу, такую как Pusher. Мы предпочтем последнее в этой статье.
  • Клиент инициирует подключение веб-сокета к серверу веб-сокетов и получает уникальный идентификатор при успешном соединении.
  • Как только соединение будет успешным, клиент подписывается на определенные каналы, по которым он хочет получать события.
  • Наконец, по подписанному каналу клиент регистрирует события, которые он хотел бы прослушать.
  • Теперь на стороне сервера, когда происходит определенное событие, мы сообщаем серверу веб-сокетов, предоставляя ему имя канала и имя события.
  • И, наконец, сервер веб-сокетов передает это событие зарегистрированным клиентам на этом конкретном канале.

Не беспокойтесь, если это выглядит слишком много за один раз; вы получите это, когда мы перейдем к этой статье.

Затем давайте посмотрим на файл конфигурации broadcasting по умолчанию в config/broadcasting.php.

По умолчанию Laravel поддерживает несколько адаптеров в своем ядре.

В этой статье мы собираемся использовать адаптер Pusher. Для целей отладки вы также можете использовать адаптер log. Конечно, если вы используете адаптер log, клиент не получит никаких уведомлений о событиях, и он будет зарегистрирован только в файле laravel.log.

Из следующего раздела дальше мы сразу же погрузимся в фактическую реализацию вышеупомянутого варианта использования.

Настройка предварительных условий

В вещании существуют разные типы каналов - публичные, частные и присутствующие. Если вы хотите публиковать свои мероприятия публично, то вы должны использовать общедоступный канал. И наоборот, приватный канал используется, когда вы хотите ограничить уведомления о событиях некоторыми привтаными каналами.

В нашем случае мы хотим уведомить пользователей, когда они получат новое сообщение. И чтобы иметь право получать уведомления о трансляции, пользователь должен войти в систему. Таким образом, нам нужно будет использовать приватный канал в нашем случае.

Основная функция проверки подлинности

Во-первых, вам нужно включить стандартную систему проверки подлинности Laravel, чтобы такие функции, как регистрация, вход в систему и т.п., работали из коробки. Если вы не знаете, как это сделать, официальная документация дает быстрое представление об этом.

Pusher SDK - установка и настройка

Поскольку мы собираемся использовать сторонний сервис Pusher в качестве нашего сервера веб-сокетов, вам необходимо создать учетную запись и убедиться, что у вас есть необходимые учетные данные API. Если у вас возникли проблемы с его созданием, не стесняйтесь спрашивать меня в разделе комментариев.

Затем нам нужно установить Pusher PHP SDK, чтобы наше приложение Laravel могло отправлять уведомления на сервер веб-сокетов Pusher.

В корне своего приложения Laravel запустите следующую команду, чтобы установить его в качестве пакета composer.

Теперь давайте изменим файл конфигурации трансляции, чтобы включить адаптер Pusher в качестве нашего драйвера по умолчанию.

Как вы можете видеть, мы изменили драйвер передачи по умолчанию на Pusher. Мы также добавили параметры конфигурации cluster и encrypted , которые вы должны были получить из учетной записи Pusher, в первую очередь.

Кроме того, он извлекает значения из переменных среды. Поэтому давайте проверим, правильно ли заданы следующие переменные в файле .env.

Затем мне пришлось внести несколько изменений в пару основных файлов Laravel, чтобы сделать его совместимым с последним Pusher SDK. Конечно, я не рекомендую вносить какие-либо изменения в фреймворк, но я просто остановлюсь на том, что нужно сделать.

Откройте файл vendor vendor/laravel/framework/src/Illuminate/PusherBroadcaster.php. Просто замените фрагмент use Pusher; на use Pusher\Pusher;.

Затем давайте откроем файл vendor/laravel/framework/src/Illuminate/BroadcastManager.php и сделаем аналогичное изменение в следующем фрагменте.

Наконец, давайте включим службу broadcast в config/app.php, удалив комментарий в следующей строке.

Итак, мы установили серверные библиотеки. В следующем разделе мы рассмотрим клиентские библиотеки, которые также должны быть установлены.

Библиотеки Pusher и Laravel Echo - Установка и настройка

В вещании ответственность стороны клиента заключается в том, чтобы подписаться на каналы и прослушивать желаемые события. Под капотом это реализовано, открывая новое соединение с сервером веб-сокетов.

К счастью, нам не нужно реализовывать какие-либо сложные вещи JavaScript для этого, поскольку Laravel уже предоставляет полезную клиентскую библиотеку Laravel Echo, которая помогает нам иметь дело с сокетами на стороне клиента. Кроме того, он поддерживает сервис Pusher, который мы собираемся использовать в этой статье.

Вы можете установить Laravel Echo, используя менеджер пакетов NPM. Конечно, вам нужно установить node и npm в первую очередь, если у вас их нет. Остальное довольно просто, как будет показано в следующем фрагменте.

Нам интересен файл node_modules/laravel-echo/dist/echo.js, который вы должны скопировать в public/echo.js.

Да, я понимаю, это наверно перебор, получить всего один JavaScript файл. Если вы не хотите проходить это упражнение, вы можете загрузить файл echo.js из моего GitHub.

И с этим мы закончили настройку наших клиентских библиотек.

Настройка исходного файла

Напомним, что мы говорили о настройке приложения, которое позволяет пользователям нашего приложения отправлять сообщения друг другу. С другой стороны, мы отправим уведомления пользователям, которые вошли в систему, когда они получают новое сообщение от других пользователей.

В этом разделе мы создадим файлы, необходимые для реализации используемого use case.

Для начала давайте создадим модель Message, в которой хранятся сообщения, отправленные пользователями друг другу.

Нам также необходимо добавить несколько полей, например, to, from и message  в нашу таблицу сообщений. Итак, давайте изменим файл миграции перед запуском команды migrate.

Теперь давайте запустим команду migrate, которая создает таблицу сообщений в базе данных.

Всякий раз, когда вы хотите поднять пользовательское событие в Laravel, вы должны создать класс для этого события. В зависимости от типа события, Laravel реагирует соответственно и предпринимает необходимые действия.

Если событие является обычным событием, Laravel вызывает связанные классы слушателей. С другой стороны, если событие имеет тип вещания, Laravel отправляет это событие на сервер веб-сокета, который настроен в файле config/broadcasting.php.

Когда мы используем сервис Pusher в нашем примере, Laravel отправит события на сервер Pusher.

Давайте используем следующую команду artisan для создания настраиваемого класса событий - NewMessageNotification.

Это должно создать класс app/Events/NewMessageNotification.php. Давайте заменим содержимое этого файла следующим.

Важно отметить, что класс NewMessageNotification реализует интерфейс ShouldBroadcastNow. Таким образом, когда мы поднимаем событие, Laravel знает, что это событие должно быть транслировано.

Фактически, вы также можете реализовать интерфейс ShouldBroadcast, а Laravel добавляет событие в очередь событий. Оно будет обработано работником очереди событий, когда у него появится такая возможность. В нашем случае мы хотим передать его прямо сейчас, поэтому мы использовали интерфейс ShouldBroadcastNow.

В нашем случае мы хотим отобразить сообщение, полученное пользователем, и, таким образом, мы передали модель Message в аргументе конструктора. Таким образом, данные будут переданы вместе с событием.

Затем существует метод broadcastOn, который определяет имя канала, по которому будет транслироваться событие. В нашем случае мы использовали приватный канал, поскольку мы хотим ограничить передачу событий зарегистрированным пользователям.

Значение $this->message->to относится к идентификатору пользователя, которому будет транслироваться событие. Таким образом имя канала подобно user.{USER_ID}.

В случае частных каналов клиент должен пройти аутентификацию до установления соединения с сервером веб-сокетов. Это гарантирует, что события, которые транслируются на частных каналах, отправляются только для аутентифицированных клиентов. В нашем случае это означает, что только зарегистрированные пользователи смогут подписаться на наш канал user.{USER_ID}.

Если вы используете клиентскую библиотеку Laravel Echo для подписки на канал, вам повезло! Она автоматически заботится о части аутентификации, и вам просто нужно определить маршруты каналов.

Давайте продолжим и добавим маршрут для нашего частного канала в файле routes/channels.php.

Как вы можете видеть, мы определили маршрут user.{toUserId} для нашего приватного канала.

Второй аргумент метода канала должен быть анонимной функцией. Laravel автоматически передает зарегистрированного пользователя в качестве первого аргумента функции, а второй аргумент обычно выбирается из имени канала.

Когда клиент пытается подписаться на приватный канал user.{USER_ID}, библиотека Laravel Echo выполняет необходимую аутентификацию в фоновом режиме с помощью объекта XMLHttpRequest или более широко известного как XHR.

Таким образом мы закончили настройку, поэтому давайте продолжим и протестируем ее.

Настройка Front-End

В этом разделе мы создадим файлы, необходимые для тестирования нашего use-case.

Давайте продолжим и создадим файл контроллера в app/Http/Controllers/MessageController.php со следующим содержимым.

В методе index мы используем представление broadcast, поэтому давайте создадим файл представлений resources/views/broadcast.blade.php.

И, конечно же, нам нужно добавить маршруты и в файл routes/web.php.

В методе конструктора класса контроллера вы можете видеть, что мы использовали middleware auth, чтобы убедиться, что методы контроллера доступны только зарегистрированным пользователям.

Далее, есть метод index, который отображает вьюшку broadcast. Давайте возьмем самый важный код в файле отображения.

Во-первых, мы загружаем необходимые клиентские библиотеки, Laravel Echo и Pusher, что позволяет нам открыть соединение веб-сокетов с сервером веб-сокетов Pusher.

Затем мы создаем экземпляр Echo, предоставляя Pusher в качестве нашего адаптера и другую необходимую информацию, связанную с Pusher.

Двигаясь дальше, мы используем метод private Echo для подписки на пользователя на приватный канал user.{USER_ID}. Как мы обсуждали ранее, клиент должен пройти аутентификацию перед подпиской на приватный канал. Таким образом, объект Echo выполняет необходимую аутентификацию, отправляя XHR в фоновом режиме с необходимыми параметрами. Наконец, Laravel пытается найти маршрут user.{USER_ID}, и он должен соответствовать маршруту, который мы определили в файле routes/channels.php.

Если все пройдет хорошо, у вас должно быть соединение с веб-сокетом с сервером веб-сокетов Pusher, и он слушает события на канале user.{USER_ID}! С этого момента мы получим все входящие события на этом канале.

В нашем случае мы хотим прослушать событие NewMessageNotification, и поэтому мы использовали метод listen объекта Echo. Чтобы все было просто, мы просто выводит сообщение с помощью alert.

Таким образом, это была настройка для приема событий с сервера веб-сокетов. Затем мы рассмотрим метод send в файле контроллера, который вызывает событие трансляции.

Давайте быстро введем код метода send.

В нашем случае мы будем уведомлять зарегистрированных пользователей, когда они получат новое сообщение. Поэтому мы попытались воспроизвести это поведение в методе send.

Затем мы использовали функцию помощник event, чтобы создать событие NewMessageNotification. Поскольку событие NewMessageNotification имеет тип ShouldBroadcastNow, Laravel загружает конфигурацию broadcast по умолчанию из файла config/broadcasting.php. Наконец, он транслирует событие NewMessageNotification на настроенный сервер веб-сокетов на канал user.{USER_ID}.

В нашем случае событие будет транслироваться на сервер веб-сокетов Pusher на канал user.{USER_ID}. Если идентификатор пользователя-получателя равен 1, событие будет транслироваться по каналу user.1.

Как мы обсуждали ранее, у нас уже есть настройка, которая прослушивает события на этом канале, поэтому она должна иметь возможность получать это событие, а окно предупреждения отображается пользователю!

Давайте продолжим и рассмотрим, как вы должны тестировать этот use-case, который мы создали.

Откройте в вашем браузере адрес http://your-laravel-site-domain/message/index. Если вы еще не вошли в систему, вы будете перенаправлены на экран входа в систему. После того, как вы вошли в систему, вы должны увидеть представление, которое мы определили ранее, пока ничего интересного.

На самом деле, Laravel уже проделал довольно много работы на заднем плане для вас. Поскольку мы включили параметр Pusher.logToConsole, предоставленный клиентской библиотекой Pusher, то для целей отладки он регистрирует все события в консоли браузера. Посмотрим, что регистрируется на консоли при доступе к странице http://your-laravel-site-domain/message/index.

Было открыто соединение с веб-сокетом с сервером веб-сокетов Pusher и была подписка на прослушивание событий на приватном канале. Конечно, у вас может быть другое имя канала в вашем случае на основе идентификатора пользователя, с которым вы вошли в систему. Теперь давайте оставим эту страницу открытой, и перейдем, чтобы протестировать метод send.

Затем давайте откроем URL-адрес http://your-laravel-site-domain/message/send на другой вкладке или в другом браузере. Если вы собираетесь использовать другой браузер, вам нужно войти в систему, чтобы иметь доступ к этой странице.

Как только вы откроете страницу http://your-laravel-site-domain/message/send, вы сможете увидеть предупреждающее сообщение на другой вкладке по адресу http://your-laravel-site-domain/message/index.

Перейдем к консоли, чтобы увидеть, что только что произошло.

Как вы можете видеть, он сообщает вам, что вы только что получили событие App\Events\NewMessageNotification от сервера веб-сокетов Pusher на канале private-user.2.

Фактически, вы можете видеть, что происходит там, на стороне Pusher. Перейдите на свою учетную запись Pusher и перейдите к своему приложению. В Debug Console вы должны иметь возможность видеть сообщения, которые регистрируются.

Pusher Dashboard

И на этом мы подходим к концу этой статьи! Надеюсь, это было не так уж и много, так как я пытался максимально все упростить.

Заключение

Сегодня мы рассмотрели одну из наименее обсуждаемых особенностей Laravel- broadcasting. Она позволяет отправлять уведомления в режиме реального времени с помощью веб-сокетов. На протяжении всей этой статьи мы построили реальный пример, демонстрирующий вышеупомянутую концепцию.

Да, я знаю, придется много чего понять в этой статье, поэтому не стесняйтесь использовать фид комментариев ниже, если у вас возникнут проблемы во время реализации.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.