В Laravel 5.1 платформа включает в себя функциональность, называемую трансляцией событий, которая позволяет легко создавать приложения в реальном времени на PHP. Благодаря этой новой функциональности приложение может публиковать события в различных облачных решениях PubSub в реальном времени, таких как Pusher или Redis.
В этой статье мы рассмотрим простое приложение todo и превратим его в приложение реального времени, используя события вещания Laravel.
Скачать и установить приложение
Самый простой способ начать работу — раскрутить экземпляр Homestead Improved . Если вы не хотите использовать Homestead Improved, в вашей системе должны быть установлены git и composer .
Мы поместим стартовый код в каталог с именем todo-app
путем клонирования git-репозитория.
git clone https://github.com/cwt137/l51-todo-app todo-app
После завершения клонирования перейдите в каталог todo-app
. Нам нужно установить все зависимости приложения, выполнив следующую команду (в зависимости от того, как настроен ваш композитор, команда может немного отличаться):
composer install
После того, как все зависимости установлены, мы должны настроить нашу базу данных.
php artisan migrate
Тестирование приложения не в реальном времени
Это приложение теперь функционально, но без функции реального времени, предоставляемой вещательными событиями Laravel. Откройте домашнюю страницу в двух браузерах и разместите их рядом, чтобы вы могли сделать сравнение. Если у вас нет двух разных браузеров, вы можете использовать два окна браузера.
Управляйте списком задач в первом окне браузера. Затем сделайте что-нибудь во втором окне браузера. Вы заметите, что другое окно браузера, в котором вы не находились, не обновляется без нажатия кнопки «Обновить». Это потому, что в реальном времени нет функциональности. Давайте добавим немного.
Добавление возможностей реального времени в приложение
Добавление возможностей реального времени позволит обоим окнам браузера обновлять свое содержимое, не дожидаясь нажатия кнопки обновления.
В этом примере мы определим три класса событий Laravel, которые запускаются в разное время в нашем приложении. Одним событием является событие ItemCreated
, которое запускается при создании нового элемента. Второе событие — это событие ItemUpdated
, которое запускается при обновлении элемента (помечается как завершенный или незавершенный). Последнее — это событие ItemDeleted
, которое запускается при удалении элемента из списка задач.
Вещательные события
Для трансляции событий мы создадим обычное событие Laravel, но мы реализуем интерфейс с названием ShouldBroadcast
. Если Laravel видит, что класс событий реализует ShouldBroadcast
он знает, что это широковещательное событие. Этот интерфейс требует от нас определить метод внутри нашего класса событий, который называется broadcastOn
. Он должен возвращать массив строк, которые являются каналами, по которым должно транслироваться это событие.
Чтобы создать классы событий, которые нам нужны, запустите некоторые команды
php artisan make:event ItemCreated php artisan make:event ItemUpdated php artisan make:event ItemDeleted
Откройте app/Events/ItemCreated.php
и замените содержимое следующим кодом:
<?php namespace App\Events; use App\Item; use App\Events\Event; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class ItemCreated extends Event implements ShouldBroadcast { use SerializesModels; public $id; /** * Create a new event instance. * * @param Item $item * @return void */ public function __construct(Item $item) { $this->id = $item->id; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return ['itemAction']; } }
Система событий Laravel будет сериализовывать этот объект и транслировать его в облачную систему в реальном времени, используя канал itemAction
. Следующая пара событий похожа на первую.
Откройте app/Events/ItemUpdated.php
и замените содержимое следующим кодом:
<?php namespace App\Events; use App\Item; use App\Events\Event; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class ItemUpdated extends Event implements ShouldBroadcast { use SerializesModels; public $id; public $isCompleted; /** * Create a new event instance. * * @param Item $item * @return void */ public function __construct(Item $item) { $this->id = $item->id; $this->isCompleted = (bool) $item->isCompleted; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return ['itemAction']; } }
Откройте app/Events/ItemDeleted.php
и замените содержимое следующим кодом:
<?php namespace App\Events; use App\Item; use App\Events\Event; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class ItemDeleted extends Event implements ShouldBroadcast { use SerializesModels; public $id; /** * Create a new event instance. * * @param Item $item * @return void */ public function __construct(Item $item) { $this->id = $item->id; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return ['itemAction']; } }
События базы данных
Есть несколько мест, в которых мы могли бы проводить мероприятия для нашего проекта. Мы можем сделать это внутри контроллера или внутри триггеров событий базы данных. В этом примере мы будем использовать триггеры базы данных, потому что они кажутся мне более естественными и не наполняют контроллер дополнительными вещами. Кроме того, помещая логику запуска событий в слой базы данных, это позволяет запускать события, когда создается программа из командной строки или когда приложение создается как задание cron.
Eloquent, библиотека базы данных, генерирует события каждый раз, когда модель создается, сохраняется после обновления или удаляется. Мы будем слушать эти события, чтобы мы могли запускать наши собственные трансляции. Это будет сделано через поставщика услуг.
Откройте файл в app/Providers/AppServiceProvider.php
и замените содержимое следующим кодом:
<?php namespace App\Providers; use Event; use App\Item; use App\Events\ItemCreated; use App\Events\ItemUpdated; use App\Events\ItemDeleted; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Item::created(function ($item) { Event::fire(new ItemCreated($item)); }); Item::updated(function ($item) { Event::fire(new ItemUpdated($item)); }); Item::deleted(function ($item) { Event::fire(new ItemDeleted($item)); }); } /** * Register any application services. * * @return void */ public function register() { // } }
толкатель
Облачный сервис в реальном времени, который мы будем использовать в этом примере, — Pusher. Поддержка этого сервиса встроена в Laravel и является самой простой в настройке.
Постановка на учет
Мы должны зарегистрироваться для учетной записи, чтобы получить набор учетных данных. После регистрации на сайте Pusher перейдите на экран администратора и создайте новое приложение под названием todo-app
. app_id
, key
и secret
. Нам это понадобится позже.
Pusher PHP Server Library
Чтобы наше приложение использовало Pusher, мы должны добавить библиотеку серверов в наш проект. Это делается с помощью композитора.
composer require 'pusher/pusher-php-server:2.2.1'
JavaScript
Мы добавим немного JavaScript внизу нашей домашней страницы. Откройте resources/views/index.blade.php
, шаблон resources/views/index.blade.php
для домашней страницы, и поместите следующий код непосредственно перед закрывающим тегом body
<script src="//js.pusher.com/2.2/pusher.min.js"></script> <script> var pusher = new Pusher("{{ env(PUSHER_KEY) }}"); </script> <script src="js/pusher.js"></script>
Приведенный выше код загружает клиентскую библиотеку Pusher Javascript, создает экземпляр объекта Pusher, передавая наш ключ в конструктор, и загружает логику нашего приложения Pusher.
В начальном приложении элементы были удалены и добавлены на основе событий, происходящих на странице (отправка формы, нажатие значка удаления и т. Д.). Вот почему, когда мы открыли два окна браузера, оба не обновились. В одном окне браузера не видно, что происходит в другом окне браузера. Чтобы приложение работало в режиме реального времени, мы будем добавлять и удалять элементы на основе событий, поступающих от Pusher. Но сначала откройте public/js/app.js
и закомментируйте все вызовы addItem()
и removeItem()
. Не удаляйте два объявления функций в верхней части файла.
Создайте файл public/js/pusher.js
и вставьте в него следующий код.
( function( $, pusher, addItem, removeItem ) { var itemActionChannel = pusher.subscribe( 'itemAction' ); itemActionChannel.bind( "App\\Events\\ItemCreated", function( data ) { addItem( data.id, false ); } ); itemActionChannel.bind( "App\\Events\\ItemUpdated", function( data ) { removeItem( data.id ); addItem( data.id, data.isCompleted ); } ); itemActionChannel.bind( "App\\Events\\ItemDeleted", function( data ) { removeItem( data.id ); } ); } )( jQuery, pusher, addItem, removeItem);
Приложение подписывается на канал itemAction
. По умолчанию Lavavel использует полное имя класса объекта события в качестве имени события Pusher. Приведенный выше код Javascript устанавливает прослушиватели для трех событий App\Events\ItemCreated
, App\Events\ItemUpdated
и App\Events\ItemDeleted
. Существуют обратные вызовы, которые обрабатывают то, что происходит, когда эти события запускаются. Как вы можете видеть, вызовы getItem
и removeItem
были перемещены в обратные вызовы для различных событий. Поэтому теперь элементы добавляются или удаляются на основе события Pusher, а не события пользователя.
Тестирование приложения в реальном времени
Чтобы проверить это приложение, вам нужно установить ключи для Pusher. По умолчанию Laravel просматривает переменные окружения для получения информации Pusher. Откройте файл .env
и поместите следующие строки внизу.
PUSHER_KEY=YOUR_PUSHER_KEY PUSHER_SECRET=YOUR_PUSHER_SECRET PUSHER_APP_ID=YOUR_PUSHER_APP_ID
Это установит переменные. Где YOUR_PUSHER_KEY
, YOUR_PUSHER_SECRET
, YOUR_PUSHER_APP_ID
— это ваш key
, назначенный Pusher, secret
и app_id
соответственно.
Снова откройте два окна браузера и управляйте списком задач в одном из них. Вы увидите, что список автоматически обновляется в другом окне браузера, не нажимая кнопку обновления.
Последние мысли
Хотя это и не рассматривается в этой статье, используемая среда является расширяемой, и если Laravel не поддерживает ваше решение в реальном времени, возможно, уже существует пакет composer с соответствующим драйвером широковещательной передачи для него. Или вы можете создать свой собственный драйвер вещания вместе с поставщиком услуг для его загрузки.
Благодаря новой функциональности вещательных событий, встроенной в Laravel 5.1, теперь разработчикам PHP стало проще создавать приложения в реальном времени. Эта новая возможность в реальном времени открывает множество возможностей, которые были доступны только для приложений, написанных для других платформ, таких как Node.js.