Статьи

Уведомления Laravel в реальном времени и подписки? Конечно, с потоком!

Эта статья была рецензирована Верном Анчетой и Юнесом Рафи . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!


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

Stream — это API для создания каналов, потоков активности и систем оповещения

Логотип Stream.io с цветами Laravel

API может использоваться со многими языками и платформами. Посетите веб-сайт и нажмите кнопку « Try the API . Выберите PHP в качестве языка выбора, так как мы будем работать с PHP. Учебник должен дать вам хороший обзор типов уведомлений, которые мы можем получить с помощью Stream. Для Laravel есть официальный пакет, который еще проще интегрировать этот сервис в любое приложение Laravel.

В этом уроке мы собираемся использовать существующий проект, чтобы опробовать Stream API. Просто клонируйте этот репо . Это простой блог Laravel 5.4, где пользователи могут выполнять операции CRUD над сообщениями в блоге. Мы добавим возможность следить за другими пользователями в ближайшее время. Затем мы создадим разделы фидов с различными типами уведомлений, сообщающих нам, кто что сделал и когда. Наше основное внимание в этом уроке будет уделяться людям, создающим новые посты в блоге и следящим друг за другом. Полный код этого урока можно найти здесь .

Настройка проекта

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

 git clone https://github.com/vickris/simple-blog 

Когда репо настроено локально, мы должны подготовить базу данных перед выполнением любых миграций. Мы будем использовать MySQL для этого урока. После настройки базы данных выполните:

 cp .env.example .env 

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

 DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret 

Так как это не новая установка Laravel, нам нужно будет запустить composer install чтобы установить различные пакеты и зависимости для этого проекта:

 composer install 

Затем запустите:

 php artisan migrate php artisan db:seed 

Приложение имеет некоторые исходные данные для генерации 10 сообщений. Если мы обслуживаем наше приложение и посещение /posts , нас должны приветствовать десять постов.

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

Следующие пользователи

Для этого мы начнем с генерации модели Follow вместе с миграцией. Заметка. однако для крупных проектов рекомендуется создать followers и following таблицы, чтобы упростить запросы:

 php artisan make:model Follow -m 

Давайте обновим метод up недавно созданной миграции следующим образом:

 public function up() { Schema::create('follows', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->index(); $table->integer('target_id')->index(); // ID of person being followed $table->timestamps(); }); } 

Здесь мы добавляем столбец user_id потому что user_id принадлежит пользователю. Давайте теперь запустим команду migrate чтобы создать следующую таблицу :

 php artisan migrate 

Нам еще предстоит определить отношения между follows и users . Откройте файл модели User и добавьте отношение:

Приложение / User.php

 [...] class User extends Authenticatable { [...] public function follows() { return $this->hasMany(Follow::class); } } 

Внутри app/Follow.php давайте добавим target_id в список массовых назначаемых атрибутов. Мы также собираемся определить отношения, определяющие, что follow принадлежит user :

Приложение / Follow.php

 [...] class Follow extends Model { protected $fillable = ['target_id']; public function user() { return $this->belongsTo(User::class); } } [...] 

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

 [...] Route::group(['middleware' => ['auth']], function () { [...] Route::get('/users', 'FollowController@index'); Route::post('/follow/{user}', 'FollowController@follow'); Route::delete('/unfollow/{user}', 'FollowController@unfollow'); }); [...] 

Мы хотим ограничить действия unfollow и unfollow для аутентифицированных пользователей, поэтому мы поместили эти маршруты в группу маршрутов с помощью промежуточного программного обеспечения auth .

Первый маршрут приведет нас на страницу со списком всех пользователей. Далее мы должны создать FollowController :

 php artisan make:controller FollowController 

Затем мы определяем действие index внутри этого контроллера. Он находится внутри действия index где мы будем извлекать всех пользователей, кроме текущего зарегистрированного пользователя. Нам не нужен сценарий, в котором пользователи могут следить за собой:

приложение / HTTP / Контроллеры / FollowController.php

 [...] use App\User; use App\Follow; use Illuminate\Support\Facades\Auth; [...] class FollowController extends Controller { public function index() { return view('users.index', [ 'users' => User::where('id', '!=', Auth::id())->get() ]); } } 

У нас все еще нет представления users.index . Давайте создадим это:

ресурсы / мнение / пользователи / index.blade.php

 @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> </tr> @endforeach </tbody> </table> </div> </div> </div> </div> @endsection 

Посещая URL /users , мы должны увидеть имена, принадлежащие зарегистрированным пользователям. Мы хотим добавить кнопку рядом с именем пользователя, чтобы пользователи могли подписываться и отписываться друг от друга.

Давайте обновим только что созданный контроллер, добавив методы follow и unfollow . Но перед этим мы должны убедиться, что кто-то еще не следует за другим человеком, прежде чем выполнять последующую операцию, и наоборот. Для этого нам нужно создать небольшую вспомогательную функцию в нашей модели User :

Приложение / User.php

 class User extends Authenticatable { [...] public function isFollowing($target_id) { return (bool)$this->follows()->where('target_id', $target_id)->first(['id']); } } 

Теперь мы можем продолжить и кодировать логику для последующих действий и отписаться от действий:

приложение / HTTP / Контроллеры / FollowController.php

 class FollowController extends Controller { [...] public function follow(User $user) { if (!Auth::user()->isFollowing($user->id)) { // Create a new follow instance for the authenticated user Auth::user()->follows()->create([ 'target_id' => $user->id, ]); return back()->with('success', 'You are now friends with '. $user->name); } else { return back()->with('error', 'You are already following this person'); } } public function unfollow(User $user) { if (Auth::user()->isFollowing($user->id)) { $follow = Auth::user()->follows()->where('target_id', $user->id)->first(); $follow->delete(); return back()->with('success', 'You are no longer friends with '. $user->name); } else { return back()->with('error', 'You are not following this person'); } } } образом class FollowController extends Controller { [...] public function follow(User $user) { if (!Auth::user()->isFollowing($user->id)) { // Create a new follow instance for the authenticated user Auth::user()->follows()->create([ 'target_id' => $user->id, ]); return back()->with('success', 'You are now friends with '. $user->name); } else { return back()->with('error', 'You are already following this person'); } } public function unfollow(User $user) { if (Auth::user()->isFollowing($user->id)) { $follow = Auth::user()->follows()->where('target_id', $user->id)->first(); $follow->delete(); return back()->with('success', 'You are no longer friends with '. $user->name); } else { return back()->with('error', 'You are not following this person'); } } } 

Затем давайте обновим список просмотра для всех пользователей, чтобы рядом с именами пользователей отображались кнопки отслеживания и отмены подписки . Так как нам нужны разные варианты кнопки в зависимости от статуса подписки, мы будем использовать созданную нами вспомогательную функцию. Вставьте блок кода сразу после <td> отображающего имя в нашем представлении users.index :

ресурсы / мнение / пользователи / index.blade.php

 [...] @if (Auth::User()->isFollowing($user->id)) <td> <form action="{{url('unfollow/' . $user->id)}}" method="POST"> {{ csrf_field() }} {{ method_field('DELETE') }} <button type="submit" id="delete-follow-{{ $user->target_id }}" class="btn btn-danger"> <i class="fa fa-btn fa-trash"></i>Unfollow </button> </form> </td> @else <td> <form action="{{url('follow/' . $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 [...] 

Если мы теперь перезагрузим страницу index пользователей, мы должны увидеть вид, который выглядит следующим образом:

Список пользователей

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

Представляем Stream

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

Настроить

Давайте установим его через Composer :

 composer require get-stream/stream-laravel 

Затем мы добавляем GetStream\StreamLaravel\StreamLaravelServiceProvider в список поставщиков в config/app.php для регистрации службы:

 'providers' => [ // Other providers [...] GetStream\StreamLaravel\StreamLaravelServiceProvider::class, ], 

А также создайте для него псевдоним еще в config/app.php :

 'aliases' => [ // other aliases [...] 'FeedManager' => 'GetStream\StreamLaravel\Facades\FeedManager', ], 

Затем мы публикуем файл конфигурации с помощью этой команды:

 php artisan vendor:publish --provider="GetStream\StreamLaravel\StreamLaravelServiceProvider" 

Это создаст файл config/stream-laravel.php . Мы должны установить наши учетные данные в этом файле, как только они будут созданы на панели мониторинга потоков.

Панель управления потоком

Давайте перейдем к GetStream.io и создадим новое приложение. Вы можете дать приложению любое имя, какое захотите. Для select server location я выбрал US East но вы можете выбрать местоположение, которое наиболее близко к вам:

Приложение New Stream

Мы получаем API key API secret и API app id после его создания. Ключи доступны из панели инструментов.

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

  • user канал, который имеет тип flat ( плоские каналы отображают действия без какой-либо группировки, и это тип каналов по умолчанию в Stream ). Этот канал отображает все действия для определенного пользователя.
  • timeline которая также имеет тип flat . Этот канал показывает, что произошло недавно.
  • timeline_aggregrated который имеет aggregated тип ( агрегированные каналы отображают действия в сгруппированном формате на основе типа действия ). Этот тип канала позволяет пользователю указать формат агрегации.
  • лента notification которая имеет тип notification . Однако, как и для агрегированных каналов, уведомления могут быть помечены как прочитанные, и вы можете получить счетчик количества невидимых и непрочитанных уведомлений.

Файл конфигурации Stream-Laravel

Мы должны установить полученный API key API secret и API app id в файле config/stream-laravel.php для взаимодействия с Streams API. Мы должны также установить location для хорошей меры.

Давайте .env эти ключи и соответствующие им значения в наш файл .env затем загрузим их в наш config/stream-laravel.php с помощью вспомогательного средства env , предоставляемого Laravel.

.env

 STREAM_KEY=xxxxxxxxxx STREAM_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx STREAM_APP_ID=xxxxxx 

конфигурации / поток-laravel.php

 'api_key' => env('STREAM_KEY'), 'api_secret' => env('STREAM_SECRET'), 'api_app_id' => env('STREAM_APP_ID'), 'location' => 'us-east', 

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

Добавление сообщений в качестве действий — Eloquent ORM Integration

Stream-Laravel обеспечивает мгновенную интеграцию с моделями Eloquent — с помощью GetStream\StreamLaravel\Eloquent\ActivityTrait мы получаем автоматическое отслеживание модели Post для пользовательских каналов:

Приложение \ Post.php

 class Post extends Model { use \GetStream\StreamLaravel\Eloquent\ActivityTrait; [...] 

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

Автоматически!

Давайте проверим вещи, создав новый пост. Если теперь мы перейдем к панели управления потоками и перейдем на вкладку « Проводник », то увидим новое действие:

Новая активность

Я предлагаю удалить это действие, так как скоро мы будем обновлять нашу модель Post , меняя глагол на created . В нынешнем виде глагол app/Post . Чтобы удалить занятие, просто установите флажок рядом с занятием, и появится меню с возможностью удалить занятие. Если мы этого не сделаем, мы позже столкнемся с проблемами при отображении каналов.

Вывод

Я должен признать, что настройка Stream заняла некоторое время, но как только мы закончим с этим, мы можем начать использовать различные методы, предлагаемые пакетом stream-laravel, для создания каналов и уведомлений. В следующей части этой серии мы рассмотрим, как настроить наши модели, чтобы их можно было сохранять в лентах как действия. Мы также рассмотрим, как получать различные типы каналов и отображать их в представлении. Будьте на связи!