Трансляція подій (Broadcasting)
- Вступ
- Швидкий старт
- Встановлення на стороні сервера
- Встановлення на стороні клієнта
- Огляд концепції
- Визначення подій трансляції
- Авторизація каналів
- Трансляція подій
- Отримання трансляцій
- Канали присутності
- Трансляція Моделей
- Події клієнта
- Сповіщення
Вступ
У багатьох сучасних веб-застосунках WebSockets використовуються для реалізації інтерфейсів користувача з оновленням у реальному часі. Коли деякі дані оновлюються на сервері, повідомлення зазвичай надсилається через з'єднання WebSocket для обробки клієнтом. WebSockets забезпечують більш ефективну альтернативу постійному опитуванню сервера вашого застосунку для змін даних, які повинні відображатися у вашому інтерфейсі користувача.
Наприклад, уявіть, що ваш застосунок може експортувати дані користувача у файл CSV та надсилати його електронною поштою. Однак створення цього файлу CSV займає кілька хвилин, тому ви вирішуєте створити та надіслати CSV у межах завдання в черзі. Коли CSV створено та надіслано користувачу, ми можемо використовувати трансляцію подій, щоб відправити подію App\Events\UserDataExported, яка отримується JavaScript-ом нашого застосунку. Після отримання події ми можемо відобразити повідомлення користувачу, що їх CSV було надіслано електронною поштою, без необхідності оновлювати сторінку.
Щоб допомогти вам у створенні таких типів функцій, Laravel спрощує "трансляцію" ваших серверних подій Laravel через з'єднання WebSocket. Трансляція ваших подій Laravel дозволяє вам ділитися тими ж іменами подій та даними між вашим серверним застосунком Laravel та вашим клієнтським JavaScript-застосунком.
Основні концепції трансляції прості: клієнти підключаються до іменованих каналів на фронтенді, тоді як ваш Laravel-застосунок транслює події до цих каналів на бекенді. Ці події можуть містити будь-які додаткові дані, які ви хочете зробити доступними на фронтенді.
Підтримувані драйвери
За замовчуванням Laravel включає три серверні драйвери трансляції, з яких ви можете вибрати: Laravel Reverb, Pusher Channels та Ably.
Перш ніж зануритися в трансляцію подій, переконайтеся, що ви прочитали документацію Laravel про події та слухачі.
Швидкий старт
За замовчуванням, трансляція не увімкнена в нових Laravel застосунках. Ви можете увімкнути трансляцію, використовуючи Artisan команду install:broadcasting:
php artisan install:broadcasting
Команда install:broadcasting запитає вас, яку службу трансляції подій ви хотіли б використовувати. Крім того, вона створить файл конфігурації config/broadcasting.php та файл routes/channels.php, де ви можете зареєструвати маршрути авторизації трансляцій вашого застосунку та зворотні виклики.
Laravel підтримує декілька драйверів для трансляції з коробки: Laravel Reverb, Pusher Channels, Ably, і драйвер log для локальної розробки та налагодження. Крім того, включено драйвер null, який дозволяє вимкнути трансляцію під час тестування. Приклад конфігурації включено для кожного з цих драйверів у конфігураційному файлі config/broadcasting.php.
Вся конфігурація трансляції подій вашого застосунку зберігається у файлі конфігурації config/broadcasting.php. Не хвилюйтеся, якщо цей файл не існує у вашому застосунку; він буде створений, коли ви виконаєте команду Artisan install:broadcasting.
Наступні кроки
Після того як ви увімкнули трансляцію подій, ви готові дізнатися більше про визначення подій трансляції та прослуховування подій. Якщо ви використовуєте стартові набори Laravel для React або Vue, ви можете прослуховувати події за допомогою хука useEcho Echo.
Перш ніж транслювати будь-які події, спочатку слід налаштувати та запустити працівника черги. Уся трансляція подій здійснюється через завдання в черзі, щоб час відгуку вашого застосунку не був серйозно вплинений трансляцією подій.
Встановлення на стороні сервера
Щоб почати використовувати трансляцію подій у Laravel, нам потрібно виконати деякі налаштування в межах застосунку Laravel, а також встановити кілька пакетів.
Трансляція подій здійснюється за допомогою серверного драйвера трансляції, який транслює ваші події Laravel, щоб Laravel Echo (бібліотека JavaScript) міг отримувати їх у браузері клієнта. Не хвилюйтеся - ми пройдемо через кожну частину процесу встановлення крок за кроком.
Reverb
Щоб швидко увімкнути підтримку функцій трансляції Laravel, використовуючи Reverb як ваш транслятор подій, виконайте команду Artisan install:broadcasting з опцією --reverb. Ця команда Artisan встановить необхідні пакети Composer та NPM для Reverb і оновить файл .env вашого застосунку з відповідними змінними:
php artisan install:broadcasting --reverb
Ручна установка
При виконанні команди install:broadcasting вам буде запропоновано встановити Laravel Reverb. Звичайно, ви також можете встановити Reverb вручну за допомогою менеджера пакетів компонувальник:
composer require laravel/reverb
Після встановлення пакета, ви можете виконати команду встановлення Reverb, щоб опублікувати конфігурацію, додати необхідні змінні середовища Reverb та увімкнути трансляцію подій у вашому застосунку:
php artisan reverb:install
Ви можете знайти детальні інструкції з встановлення та використання Reverb у документації Reverb.
Pusher Channels
Щоб швидко увімкнути підтримку функцій трансляції Laravel, використовуючи Pusher як ваш транслятор подій, виконайте Artisan команду install:broadcasting з опцією --pusher. Ця Artisan команда запитає ваші облікові дані Pusher, встановить Pusher PHP та JavaScript SDK, і оновить файл .env вашого застосунку відповідними змінними:
php artisan install:broadcasting --pusher
Ручна установка
Щоб вручну встановити підтримку Pusher, слід встановити Pusher Channels PHP SDK за допомогою менеджера пакетів компонувальник:
composer require pusher/pusher-php-server
Далі, вам слід налаштувати облікові дані Pusher Channels у конфігураційному файлі config/broadcasting.php. Приклад конфігурації Pusher Channels вже включено в цей файл, що дозволяє швидко вказати ваш ключ, секрет і ID застосунку. Зазвичай, ви повинні налаштувати облікові дані Pusher Channels у файлі .env вашого застосунку:
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET="your-pusher-secret"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"
Файл config/broadcasting.php у конфігурації pusher також дозволяє вказати додаткові options, які підтримуються Channels, такі як кластер.
Потім встановіть змінну середовища BROADCAST_CONNECTION на pusher у файлі .env вашого застосунку:
BROADCAST_CONNECTION=pusher
Нарешті, ви готові встановити та налаштувати Laravel Echo, який буде отримувати події трансляції на стороні клієнта.
Ably
Документація нижче обговорює, як використовувати Ably в режимі "сумісності з Pusher". Однак команда Ably рекомендує та підтримує транслятор і клієнт Echo, які можуть скористатися унікальними можливостями, що пропонуються Ably. Для отримання додаткової інформації про використання драйверів, які підтримуються Ably, будь ласка, ознайомтеся з документацією Ably для транслятора Laravel.
Щоб швидко увімкнути підтримку функцій трансляції Laravel, використовуючи Ably як ваш транслятор подій, виконайте Artisan команду install:broadcasting з опцією --ably. Ця Artisan команда запитає ваші облікові дані Ably, встановить Ably PHP та JavaScript SDK, а також оновить файл .env вашого застосунку з відповідними змінними:
php artisan install:broadcasting --ably
Перш ніж продовжити, вам слід увімкнути підтримку протоколу Pusher у налаштуваннях вашого Ably застосунку. Ви можете увімкнути цю функцію в розділі "Protocol Adapter Settings" на панелі налаштувань вашого Ably застосунку.
Ручна установка
Щоб встановити підтримку Ably вручну, ви повинні встановити Ably PHP SDK за допомогою менеджера пакетів Composer:
composer require ably/ably-php
Далі, вам слід налаштувати ваші облікові дані Ably у файлі конфігурації config/broadcasting.php. Приклад конфігурації Ably вже включено в цей файл, що дозволяє швидко вказати ваш ключ. Зазвичай, це значення слід встановити через ABLY_KEY змінну середовища:
ABLY_KEY=your-ably-key
Потім встановіть змінну середовища BROADCAST_CONNECTION на ably у файлі .env вашого застосунку:
BROADCAST_CONNECTION=ably
Нарешті, ви готові встановити та налаштувати Laravel Echo, який буде отримувати події трансляції на стороні клієнта.
Встановлення на стороні клієнта
Reverb
Laravel Echo — це бібліотека JavaScript, яка робить підписку на канали та прослуховування подій, що транслюються вашим серверним драйвером трансляції, безболісними.
Коли ви встановлюєте Laravel Reverb за допомогою команди Artisan install:broadcasting, шаблони та конфігурація Reverb і Echo будуть автоматично інтегровані у ваш застосунок. Однак, якщо ви бажаєте вручну налаштувати Laravel Echo, ви можете зробити це, дотримуючись наведених нижче інструкцій.
Ручна установка
Щоб вручну налаштувати Laravel Echo для фронтенду вашого застосунку, спочатку встановіть пакет pusher-js, оскільки Reverb використовує протокол Pusher для підписок на WebSocket, каналів та повідомлень:
npm install --save-dev laravel-echo pusher-js
Після встановлення Echo, ви готові створити новий екземпляр Echo у JavaScript вашого застосунку. Чудовим місцем для цього є нижня частина файлу resources/js/bootstrap.js, який включено в Laravel фреймворк:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "reverb",
// key: import.meta.env.VITE_REVERB_APP_KEY,
// wsHost: import.meta.env.VITE_REVERB_HOST,
// wsPort: import.meta.env.VITE_REVERB_PORT,
// wssPort: import.meta.env.VITE_REVERB_PORT,
// forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
});
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "reverb",
// key: import.meta.env.VITE_REVERB_APP_KEY,
// wsHost: import.meta.env.VITE_REVERB_HOST,
// wsPort: import.meta.env.VITE_REVERB_PORT,
// wssPort: import.meta.env.VITE_REVERB_PORT,
// forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
// enabledTransports: ['ws', 'wss'],
});
Далі, вам слід скомпілювати ресурси вашого застосунку:
npm run build
Laravel Echo reverb мовник вимагає laravel-echo версії v1.16.0+.
Pusher Channels
Laravel Echo — це бібліотека JavaScript, яка робить підписку на канали та прослуховування подій, що транслюються вашим серверним драйвером трансляції, безболісними.
Коли ви встановлюєте підтримку трансляції за допомогою команди Artisan install:broadcasting --pusher, шаблони та конфігурація Pusher і Echo будуть автоматично додані до вашого застосунку. Однак, якщо ви бажаєте вручну налаштувати Laravel Echo, ви можете зробити це, дотримуючись наведених нижче інструкцій.
Ручна установка
Щоб вручну налаштувати Laravel Echo для фронтенду вашого застосунку, спочатку встановіть пакети laravel-echo та pusher-js, які використовують протокол Pusher для підписок на WebSocket, каналів та повідомлень:
npm install --save-dev laravel-echo pusher-js
Після встановлення Echo, ви готові створити новий екземпляр Echo у файлі resources/js/bootstrap.js вашого застосунку:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
forceTLS: true
});
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "pusher",
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
// forceTLS: true,
// wsHost: import.meta.env.VITE_PUSHER_HOST,
// wsPort: import.meta.env.VITE_PUSHER_PORT,
// wssPort: import.meta.env.VITE_PUSHER_PORT,
// enabledTransports: ["ws", "wss"],
});
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "pusher",
// key: import.meta.env.VITE_PUSHER_APP_KEY,
// cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
// forceTLS: true,
// wsHost: import.meta.env.VITE_PUSHER_HOST,
// wsPort: import.meta.env.VITE_PUSHER_PORT,
// wssPort: import.meta.env.VITE_PUSHER_PORT,
// enabledTransports: ["ws", "wss"],
});
Далі, вам слід визначити відповідні значення для змінних середовища Pusher у файлі .env вашого застосунку. Якщо ці змінні ще не існують у вашому файлі .env, вам слід їх додати:
PUSHER_APP_ID="your-pusher-app-id"
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET="your-pusher-secret"
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME="https"
PUSHER_APP_CLUSTER="mt1"
VITE_APP_NAME="${APP_NAME}"
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
Після того як ви налаштували конфігурацію Echo відповідно до потреб вашого застосунку, ви можете скомпілювати ресурси вашого застосунку:
npm run build
Щоб дізнатися більше про компіляцію JavaScript-ресурсів вашого застосунку, будь ласка, зверніться до документації на Vite.
Використання існуючого екземпляра клієнта
Якщо у вас вже є попередньо налаштований екземпляр клієнта Pusher Channels, який ви хотіли б використовувати з Echo, ви можете передати його Echo через параметр конфігурації client:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
const options = {
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY
}
window.Echo = new Echo({
...options,
client: new Pusher(options.key, options)
});
Ably
Документація нижче обговорює, як використовувати Ably в режимі "сумісності з Pusher". Однак команда Ably рекомендує та підтримує транслятор і клієнт Echo, які можуть скористатися унікальними можливостями, що пропонуються Ably. Для отримання додаткової інформації про використання драйверів, які підтримуються Ably, будь ласка, ознайомтеся з документацією Ably для Laravel транслятора.
Laravel Echo — це бібліотека JavaScript, яка робить підписку на канали та прослуховування подій, що транслюються вашим серверним драйвером трансляції, безболісними.
Коли ви встановлюєте підтримку трансляції за допомогою команди Artisan install:broadcasting --ably, шаблони та конфігурація Ably та Echo будуть автоматично додані до вашого застосунку. Однак, якщо ви бажаєте вручну налаштувати Laravel Echo, ви можете зробити це, дотримуючись наведених нижче інструкцій.
Ручна установка
Щоб вручну налаштувати Laravel Echo для фронтенду вашого застосунку, спочатку встановіть пакети laravel-echo та pusher-js, які використовують протокол Pusher для підписок на WebSocket, каналів та повідомлень:
npm install --save-dev laravel-echo pusher-js
Перш ніж продовжити, вам слід увімкнути підтримку протоколу Pusher у налаштуваннях вашого Ably застосунку. Ви можете увімкнути цю функцію в розділі "Protocol Adapter Settings" на панелі налаштувань вашого Ably застосунку.
Після встановлення Echo, ви готові створити новий екземпляр Echo у файлі resources/js/bootstrap.js вашого застосунку:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
wsHost: 'realtime-pusher.ably.io',
wsPort: 443,
disableStats: true,
encrypted: true,
});
import { configureEcho } from "@laravel/echo-react";
configureEcho({
broadcaster: "ably",
// key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
// wsHost: "realtime-pusher.ably.io",
// wsPort: 443,
// disableStats: true,
// encrypted: true,
});
import { configureEcho } from "@laravel/echo-vue";
configureEcho({
broadcaster: "ably",
// key: import.meta.env.VITE_ABLY_PUBLIC_KEY,
// wsHost: "realtime-pusher.ably.io",
// wsPort: 443,
// disableStats: true,
// encrypted: true,
});
Ви могли помітити, що наша конфігурація Ably Echo посилається на змінну середовища VITE_ABLY_PUBLIC_KEY. Значення цієї змінної має бути вашим публічним ключем Ably. Ваш публічний ключ — це частина вашого ключа Ably, яка знаходиться перед символом :.
Після того як ви налаштували конфігурацію Echo відповідно до ваших потреб, ви можете скомпілювати ресурси вашого застосунку:
npm run dev
Щоб дізнатися більше про компіляцію JavaScript-ресурсів вашого застосунку, будь ласка, зверніться до документації на Vite.
Огляд концепції
Трансляція подій у Laravel дозволяє транслювати події на стороні сервера Laravel до вашого JavaScript-застосунку на стороні клієнта, використовуючи підхід на основі драйверів до WebSockets. Наразі Laravel постачається з драйверами Laravel Reverb, Pusher Channels та Ably. Події можуть бути легко спожиті на стороні клієнта за допомогою JavaScript-пакету Laravel Echo.
Події транслюються через "канали", які можуть бути визначені як публічні або приватні. Будь-який відвідувач вашого застосунку може підписатися на публічний канал без будь-якої автентифікації або авторизації; однак, щоб підписатися на приватний канал, користувач повинен бути автентифікований і авторизований для прослуховування цього каналу.
Використання прикладу застосунку
Перш ніж зануритися в кожен компонент трансляції подій, давайте розглянемо загальний огляд, використовуючи інтернет-магазин як приклад.
У нашому застосунку, припустимо, у нас є сторінка, яка дозволяє користувачам переглядати статус доставки їхніх замовлень. Також припустимо, що подія OrderShipmentStatusUpdated викликається, коли оновлення статусу доставки обробляється застосунком:
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
Інтерфейс ShouldBroadcast
Коли користувач переглядає одне зі своїх замовлень, ми не хочемо, щоб він мав оновлювати сторінку для перегляду оновлень статусу. Натомість, ми хочемо транслювати оновлення до застосунку, як тільки вони створюються. Тому, нам потрібно позначити подію OrderShipmentStatusUpdated інтерфейсом ShouldBroadcast. Це вкаже Laravel транслювати подію, коли вона викликається:
<?php namespace App\Events; use App\Models\Order; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class OrderShipmentStatusUpdated implements ShouldBroadcast { /** * Екземпляр замовлення. * * @var \App\Models\Order */ public $order; }
Інтерфейс ShouldBroadcast вимагає, щоб наша подія визначила метод broadcastOn. Цей метод відповідає за повернення каналів, на яких подія повинна транслюватися. Порожня заготівка цього методу вже визначена в згенерованих класах подій, тому нам потрібно лише заповнити його деталі. Ми хочемо, щоб лише творець замовлення міг переглядати оновлення статусу, тому ми будемо транслювати подію на приватному каналі, який прив'язаний до замовлення:
use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\PrivateChannel; /** * Отримати канал, на якому має транслюватися подія. */ public function broadcastOn(): Channel { return new PrivateChannel('orders.'.$this->order->id); }
Якщо ви бажаєте, щоб подія транслювалася на кількох каналах, ви можете повернути масив замість цього:
use Illuminate\Broadcasting\PrivateChannel; /** * Отримати канали, на яких має транслюватися подія. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('orders.'.$this->order->id), // ... ]; }
Авторизація каналів
Пам'ятайте, користувачі повинні бути авторизовані для прослуховування приватних каналів. Ми можемо визначити наші правила авторизації каналів у файлі routes/channels.php нашого застосунку. У цьому прикладі нам потрібно перевірити, що будь-який користувач, який намагається прослуховувати приватний канал orders.1, насправді є творцем замовлення:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
Метод channel приймає два аргументи: ім'я каналу та зворотний виклик, який повертає true або false, вказуючи, чи авторизований користувач слухати канал.
Усі зворотні виклики авторизації отримують поточного автентифікованого користувача як свій перший аргумент і будь-які додаткові параметри підстановки як наступні аргументи. У цьому прикладі ми використовуємо заповнювач {orderId}, щоб вказати, що частина "ID" у назві каналу є підстановкою.
Прослуховування трансляцій подій
Далі, все, що залишається, це слухати подію в нашому JavaScript-застосунку. Ми можемо зробити це, використовуючи Laravel Echo. Вбудовані React і Vue хуки Laravel Echo роблять початок роботи простим, і, за замовчуванням, всі публічні властивості події будуть включені в трансляційну подію:
import { useEcho } from "@laravel/echo-react"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, );
<script setup lang="ts"> import { useEcho } from "@laravel/echo-vue"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, ); </script>
Визначення Подій Трансляції
Щоб повідомити Laravel, що певна подія повинна бути транслювана, ви повинні реалізувати інтерфейс Illuminate\Contracts\Broadcasting\ShouldBroadcast у класі події. Цей інтерфейс вже імпортований у всі класи подій, згенеровані фреймворком, тому ви можете легко додати його до будь-якої з ваших подій.
Інтерфейс ShouldBroadcast вимагає реалізувати один метод: broadcastOn. Метод broadcastOn повинен повертати канал або масив каналів, на яких подія повинна транслюватися. Канали повинні бути екземплярами Channel, PrivateChannel або PresenceChannel. Екземпляри Channel представляють публічні канали, на які може підписатися будь-який користувач, тоді як PrivateChannels і PresenceChannels представляють приватні канали, які вимагають авторизації каналу:
<?php namespace App\Events; use App\Models\User; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class ServerCreated implements ShouldBroadcast { use SerializesModels; /** * Створити новий екземпляр події. */ public function __construct( public User $user, ) {} /** * Отримати канали, на які має транслюватися подія. * * @return array<int, \Illuminate\Broadcasting\Channel> */ public function broadcastOn(): array { return [ new PrivateChannel('user.'.$this->user->id), ]; } }
Після реалізації інтерфейсу ShouldBroadcast вам потрібно лише викликати подію, як ви зазвичай це робите. Після того, як подія була викликана, завдання в черзі автоматично транслюватиме подію, використовуючи вказаний вами драйвер трансляції.
Ім'я трансляції
За замовчуванням Laravel буде транслювати подію, використовуючи ім'я класу події. Однак, ви можете налаштувати ім'я трансляції, визначивши метод broadcastAs у події:
/** *Ім’я трансляції події. */ public function broadcastAs(): string { return 'server.created'; }
Якщо ви налаштовуєте ім'я трансляції за допомогою методу broadcastAs, ви повинні переконатися, що зареєстрували ваш слухач з провідним символом .. Це вкаже Echo не додавати простір імен застосунку до події:
.listen('.server.created', function (e) {
// ...
});
Дані трансляції
Коли подія транслюється, всі її public властивості автоматично серіалізуються і транслюються як дані події, дозволяючи вам отримати доступ до будь-яких її публічних даних з вашого JavaScript-застосунку. Отже, наприклад, якщо ваша подія має одну публічну властивість $user, яка містить Eloquent модель, дані трансляції події будуть:
{ "user": { "id": 1, "name": "Patrick Stewart" ... } }
Однак, якщо ви бажаєте мати більш детальний контроль над вашим переданим в ефір вмістом, ви можете додати метод broadcastWith до вашої події. Цей метод повинен повертати масив даних, які ви бажаєте передати в ефір як вміст події:
/** * Отримати дані для трансляції. * * @return array<string, mixed> */ public function broadcastWith(): array { return ['id' => $this->user->id]; }
Черга Трансляції
За замовчуванням кожна подія трансляції розміщується в черзі за замовчуванням для з'єднання черги за замовчуванням, вказаного у вашому конфігураційному файлі queue.php. Ви можете налаштувати з'єднання черги та ім'я, яке використовується транслятором, визначивши властивості connection та queue у вашому класі події:
/**
* Ім'я з'єднання черги, яке слід використовувати при трансляції події.
*
* @var string
*/
public $connection = 'redis';
/**
* Ім'я черги, в яку слід помістити завдання трансляції.
*
* @var string
*/
public $queue = 'default';
Альтернативно, ви можете налаштувати ім'я черги, визначивши метод broadcastQueue у вашій події:
/**
* Назва черги, в яку слід помістити завдання трансляції.
*/
public function broadcastQueue(): string
{
return 'default';
}
Якщо ви хочете транслювати вашу подію, використовуючи чергу sync замість драйвера черги за замовчуванням, ви можете реалізувати інтерфейс ShouldBroadcastNow замість ShouldBroadcast:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class OrderShipmentStatusUpdated implements ShouldBroadcastNow
{
// ...
}
Умови Трансляції
Іноді ви хочете транслювати вашу подію лише якщо задана умова є істинною. Ви можете визначити ці умови, додавши метод broadcastWhen до вашого класу події:
/**
* Визначте, чи слід транслювати цю подію.
*/
public function broadcastWhen(): bool
{
return $this->order->value > 100;
}
Трансляція та Транзакції Бази Даних
Коли події трансляції відправляються в межах транзакцій бази даних, вони можуть бути оброблені чергою до того, як транзакція бази даних буде зафіксована. Коли це відбувається, будь-які оновлення, які ви зробили в моделях або записах бази даних під час транзакції, можуть ще не відображатися в базі даних. Крім того, будь-які моделі або записи бази даних, створені в межах транзакції, можуть не існувати в базі даних. Якщо ваша подія залежить від цих моделей, можуть виникнути несподівані помилки, коли завдання, яке транслює подію, буде оброблено.
Якщо параметр конфігурації after_commit вашого з'єднання черги встановлено на false, ви все ще можете вказати, що певна подія трансляції повинна бути відправлена після того, як всі відкриті транзакції бази даних будуть зафіксовані, реалізувавши інтерфейс ShouldDispatchAfterCommit у класі події:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
use Illuminate\Queue\SerializesModels;
class ServerCreated implements ShouldBroadcast, ShouldDispatchAfterCommit
{
use SerializesModels;
}
Щоб дізнатися більше про вирішення цих проблем, перегляньте документацію щодо чергових завдань і транзакцій бази даних.
Авторизація каналів
Приватні канали вимагають авторизації, щоб поточний автентифікований користувач дійсно міг слухати канал. Це досягається шляхом здійснення HTTP-запиту до вашого Laravel-застосунку з назвою каналу, що дозволяє вашому застосунку визначити, чи може користувач слухати цей канал. При використанні Laravel Echo, HTTP-запит для авторизації підписок на приватні канали буде здійснено автоматично.
Коли трансляція увімкнена, Laravel автоматично реєструє маршрут /broadcasting/auth для обробки запитів авторизації. Маршрут /broadcasting/auth автоматично розміщується в групі middleware web.
Визначення авторизації каналу
Далі, нам потрібно визначити логіку, яка фактично визначатиме, чи може поточний автентифікований користувач слухати даний канал. Це робиться у файлі routes/channels.php, який був створений командою Artisan install:broadcasting. У цьому файлі ви можете використовувати метод Broadcast::channel для реєстрації зворотних викликів авторизації каналу:
use App\Models\User;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
Метод channel приймає два аргументи: ім'я каналу та зворотний виклик, який повертає true або false, вказуючи, чи авторизований користувач слухати канал.
Усі зворотні виклики авторизації отримують поточного автентифікованого користувача як свій перший аргумент і будь-які додаткові параметри підстановки як наступні аргументи. У цьому прикладі ми використовуємо заповнювач {orderId}, щоб вказати, що частина "ID" у назві каналу є підстановкою.
Ви можете переглянути список зворотних викликів авторизації трансляції вашого застосунку, використовуючи Artisan команду channel:list:
php artisan channel:list
Прив’язка моделі до авторизації
Так само, як і HTTP-маршрути, маршрути каналів можуть використовувати неявне та явне зв'язування моделей маршруту. Наприклад, замість отримання рядкового або числового ідентифікатора замовлення, ви можете запросити фактичний екземпляр моделі Order:
use App\Models\Order;
use App\Models\User;
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
return $user->id === $order->user_id;
});
На відміну від прив'язки моделі маршруту HTTP, прив'язка моделі каналу не підтримує автоматичне неявне обмеження прив'язки моделі. Однак це рідко є проблемою, оскільки більшість каналів можуть бути обмежені на основі унікального первинного ключа однієї моделі.
Автентифікація у зворотному виклику авторизації
Приватні та канали присутності трансляції автентифікують поточного користувача через типовий захисник автентифікації вашого застосунку. Якщо користувач не автентифікований, авторизація каналу автоматично відхиляється, і зворотний виклик авторизації ніколи не виконується. Однак, ви можете призначити декілька користувацьких захисників, які повинні автентифікувати вхідний запит, якщо це необхідно:
Broadcast::channel('channel', function () {
// ...
}, ['guards' => ['web', 'admin']]);
Визначення Класів Каналів
Якщо ваш застосунок використовує багато різних каналів, ваш файл routes/channels.php може стати громіздким. Тому, замість використання замикань для авторизації каналів, ви можете використовувати класи каналів. Щоб згенерувати клас каналу, використовуйте команду Artisan make:channel. Ця команда розмістить новий клас каналу в директорії App/Broadcasting.
php artisan make:channel OrderChannel
Далі зареєструйте свій канал у файлі routes/channels.php:
use App\Broadcasting\OrderChannel;
Broadcast::channel('orders.{order}', OrderChannel::class);
Нарешті, ви можете розмістити логіку авторизації для вашого каналу в методі join класу каналу. Цей метод join міститиме ту ж логіку, яку ви зазвичай розміщували б у вашому замиканні авторизації каналу. Ви також можете скористатися прив'язкою моделі каналу:
<?php
namespace App\Broadcasting;
use App\Models\Order;
use App\Models\User;
class OrderChannel
{
/**
* Створіть новий екземпляр каналу.
*/
public function __construct() {}
/**
* Автентифікуйте доступ користувача до каналу.
*/
public function join(User $user, Order $order): array|bool
{
return $user->id === $order->user_id;
}
}
Як і багато інших класів у Laravel, класи каналів будуть автоматично вирішені за допомогою сервіс-контейнера. Тому ви можете вказати будь-які залежності, необхідні вашому каналу, у його конструкторі.
Трансляція Подій
Як тільки ви визначили подію і позначили її інтерфейсом ShouldBroadcast, вам потрібно лише викликати подію за допомогою методу dispatch події. Диспетчер подій помітить, що подія позначена інтерфейсом ShouldBroadcast і поставить подію в чергу для трансляції:
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
Тільки для інших
Коли ви створюєте застосунок, що використовує трансляцію подій, іноді може виникнути потреба транслювати подію всім підписникам певного каналу, окрім поточного користувача. Ви можете досягти цього, використовуючи хелпер broadcast та метод toOthers:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->toOthers();
Щоб краще зрозуміти, коли ви можете захотіти використати метод toOthers, давайте уявимо застосунок списку завдань, де користувач може створити нове завдання, ввівши назву завдання. Щоб створити завдання, ваш застосунок може зробити запит до URL-адреси /task, яка транслює створення завдання і повертає JSON-представлення нового завдання. Коли ваш JavaScript-застосунок отримує відповідь від кінцевої точки, він може безпосередньо вставити нове завдання у свій список завдань ось так:
axios.post('/task', task)
.then((response) => {
this.tasks.push(response.data);
});
Однак пам'ятайте, що ми також транслюємо створення завдання. Якщо ваш JavaScript-застосунок також слухає цю подію, щоб додати завдання до списку завдань, у вашому списку будуть дублікати завдань: одне з кінцевої точки та одне з трансляції. Ви можете вирішити це, використовуючи метод toOthers, щоб вказати транслятору не транслювати подію поточному користувачу.
Вашій події потрібно використовувати трейд Illuminate\Broadcasting\InteractsWithSockets, щоб викликати метод toOthers.
Конфігурація
Коли ви ініціалізуєте екземпляр Laravel Echo, до з'єднання призначається socket ID. Якщо ви використовуєте глобальний екземпляр Axios для здійснення HTTP-запитів з вашого JavaScript-застосунку, socket ID автоматично буде додано до кожного вихідного запиту як заголовок X-Socket-ID. Потім, коли ви викликаєте метод toOthers, Laravel витягне socket ID із заголовка і накаже мовнику не транслювати на жодні з'єднання з цим socket ID.
Якщо ви не використовуєте глобальний екземпляр Axios, вам потрібно вручну налаштувати ваш JavaScript-застосунок для відправки заголовка X-Socket-ID з усіма вихідними запитами. Ви можете отримати socket ID, використовуючи метод Echo.socketId:
var socketId = Echo.socketId();
Налаштування з'єднання
Якщо ваш застосунок взаємодіє з кількома з'єднаннями для трансляції і ви хочете транслювати подію, використовуючи транслятор, відмінний від вашого за замовчуванням, ви можете вказати, до якого з'єднання надсилати подію, використовуючи метод via:
use App\Events\OrderShipmentStatusUpdated;
broadcast(new OrderShipmentStatusUpdated($update))->via('pusher');
Альтернативно, ви можете вказати з'єднання трансляції події, викликавши метод broadcastVia у конструкторі події. Однак, перед цим, ви повинні переконатися, що клас події використовує трейт InteractsWithBroadcasting:
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Broadcasting\InteractsWithBroadcasting; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Queue\SerializesModels; class OrderShipmentStatusUpdated implements ShouldBroadcast { use InteractsWithBroadcasting; /** * Створити новий екземпляр події. */ public function __construct() { $this->broadcastVia('pusher'); } }
Анонімні події
Іноді ви можете захотіти транслювати просту подію на фронтенд вашого застосунку без створення окремого класу події. Щоб це врахувати, фасад Broadcast дозволяє транслювати "анонімні події":
Broadcast::on('orders.'.$order->id)->send();
Наведений вище приклад транслюватиме наступну подію:
{
"event": "AnonymousEvent",
"data": "[]",
"channel": "orders.1"
}
Використовуючи методи as та with, ви можете налаштувати ім'я події та дані:
Broadcast::on('orders.'.$order->id)
->as('OrderPlaced')
->with($order)
->send();
Наведений вище приклад транслюватиме подію, як показано нижче:
{
"event": "OrderPlaced",
"data": "{ id: 1, total: 100 }",
"channel": "orders.1"
}
Якщо ви хочете транслювати анонімну подію на приватному або присутньому каналі, ви можете скористатися методами private та presence:
Broadcast::private('orders.'.$order->id)->send();
Broadcast::presence('channels.'.$channel->id)->send();
Трансляція анонімної події за допомогою методу send відправляє подію в чергу вашого застосунку для обробки. Однак, якщо ви хочете транслювати подію негайно, ви можете використовувати метод sendNow:
Broadcast::on('orders.'.$order->id)->sendNow();
Щоб транслювати подію всім підписникам каналу, окрім поточного автентифікованого користувача, ви можете викликати метод toOthers:
Broadcast::on('orders.'.$order->id)
->toOthers()
->send();
Порятунок Трансляцій
Коли сервер черги вашого застосунку недоступний або Laravel стикається з помилкою під час трансляції події, виникає виняток, який зазвичай призводить до того, що кінцевий користувач бачить помилку застосунку. Оскільки трансляція подій часто є додатковою до основної функціональності вашого застосунку, ви можете запобігти цим виняткам від порушення користувацького досвіду, реалізувавши інтерфейс ShouldRescue у ваших подіях.
Події, які реалізують інтерфейс ShouldRescue, автоматично використовують допоміжну функцію rescue Laravel під час спроб трансляції. Ця допоміжна функція перехоплює будь-які винятки, повідомляє про них обробнику винятків вашого застосунку для ведення журналу та дозволяє застосунку продовжувати виконання без переривання робочого процесу користувача:
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldRescue;
class ServerCreated implements ShouldBroadcast, ShouldRescue
{
// ...
}
Отримання Трансляцій
Прослуховування подій
Після того як ви встановили та ініціалізували Laravel Echo, ви готові почати слухати події, які транслюються з вашого Laravel застосунку. Спочатку використайте метод channel для отримання екземпляра каналу, потім викличте метод listen для прослуховування вказаної події:
Echo.channel(`orders.${this.order.id}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order.name);
});
Якщо ви хочете слухати події на приватному каналі, використовуйте метод private. Ви можете продовжувати ланцюжити виклики до методу listen, щоб слухати кілька подій на одному каналі:
Echo.private(`orders.${this.order.id}`)
.listen(/* ... */)
.listen(/* ... */)
.listen(/* ... */);
Припинити прослуховування подій
Якщо ви хочете припинити прослуховування певної події без виходу з каналу, ви можете використовувати метод stopListening:
Echo.private(`orders.${this.order.id}`)
.stopListening('OrderShipmentStatusUpdated');
Вихід з каналу
Щоб покинути канал, ви можете викликати метод leaveChannel на вашому екземплярі Echo:
Echo.leaveChannel(`orders.${this.order.id}`);
Якщо ви хочете залишити канал, а також його пов'язані приватні та присутні канали, ви можете викликати метод leave:
Echo.leave(`orders.${this.order.id}`);
Простори імен
Ви могли помітити в наведених вище прикладах, що ми не вказали повний простір імен App\Events для класів подій. Це тому, що Echo автоматично припускає, що події знаходяться в просторі імен App\Events. Однак ви можете налаштувати кореневий простір імен, коли створюєте екземпляр Echo, передавши параметр конфігурації namespace:
window.Echo = new Echo({
broadcaster: 'pusher',
// ...
namespace: 'App.Other.Namespace'
});
Альтернативно, ви можете додати префікс до класів подій за допомогою . при підписці на них за допомогою Echo. Це дозволить вам завжди вказувати повністю кваліфіковане ім'я класу:
Echo.channel('orders')
.listen('.Namespace\\Event\\Class', (e) => {
// ...
});
Використання React або Vue
Laravel Echo включає React та Vue хуки, які роблять прослуховування подій безболісним. Щоб почати, викличте хук useEcho, який використовується для прослуховування приватних подій. Хук useEcho автоматично залишить канали, коли компонент, що використовує його, буде демонтовано:
import { useEcho } from "@laravel/echo-react"; useEcho( `orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => { console.log(e.order); }, );
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
</script>
Ви можете прослуховувати кілька подій, надаючи масив подій до useEcho:
useEcho(
`orders.${orderId}`,
["OrderShipmentStatusUpdated", "OrderShipped"],
(e) => {
console.log(e.order);
},
);
Ви також можете вказати форму даних корисного навантаження події трансляції, забезпечуючи більшу безпеку типів і зручність редагування:
type OrderData = {
order: {
id: number;
user: {
id: number;
name: string;
};
created_at: string;
};
};
useEcho<OrderData>(`orders.${orderId}`, "OrderShipmentStatusUpdated", (e) => {
console.log(e.order.id);
console.log(e.order.user.id);
});
Хук useEcho автоматично залишатиме канали, коли компонент, що використовує, буде демонтовано; однак, ви можете використовувати повернені функції для ручного зупинення / запуску прослуховування каналів програмно, коли це необхідно:
import { useEcho } from "@laravel/echo-react";
const { leaveChannel, leave, stopListening, listen } = useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
// Stop listening without leaving channel...
stopListening();
// Start listening again...
listen();
// Leave channel...
leaveChannel();
// Leave a channel and also its associated private and presence channels...
leave();
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { leaveChannel, leave, stopListening, listen } = useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
// Stop listening without leaving channel...
stopListening();
// Start listening again...
listen();
// Leave channel...
leaveChannel();
// Leave a channel and also its associated private and presence channels...
leave();
</script>
Підключення до публічних каналів
Щоб підключитися до публічного каналу, ви можете використовувати хук useEchoPublic:
import { useEchoPublic } from "@laravel/echo-react"; useEchoPublic("posts", "PostPublished", (e) => { console.log(e.post); });
<script setup lang="ts">
import { useEchoPublic } from "@laravel/echo-vue";
useEchoPublic("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
Підключення до Presence-каналів
Щоб підключитися до каналу присутності, ви можете використовувати хук useEchoPresence:
import { useEchoPresence } from "@laravel/echo-react"; useEchoPresence("posts", "PostPublished", (e) => { console.log(e.post); });
<script setup lang="ts">
import { useEchoPresence } from "@laravel/echo-vue";
useEchoPresence("posts", "PostPublished", (e) => {
console.log(e.post);
});
</script>
Канали присутності
Канали присутності базуються на безпеці приватних каналів, додаючи можливість дізнатися, хто підписаний на канал. Це полегшує створення потужних, спільних функцій застосунку, таких як сповіщення користувачів, коли інший користувач переглядає ту саму сторінку, або перелік учасників чату.
Авторизація каналів присутності
Усі канали присутності також є приватними каналами; тому користувачі повинні бути авторизовані для доступу до них. Однак, при визначенні зворотних викликів авторизації для каналів присутності, ви не повернете true, якщо користувач авторизований для приєднання до каналу. Натомість, ви повинні повернути масив даних про користувача.
Дані, повернені зворотним викликом авторизації, будуть доступні для слухачів подій каналу присутності у вашому JavaScript-застосунку. Якщо користувач не авторизований для приєднання до каналу присутності, ви повинні повернути false або null:
use App\Models\User;
Broadcast::channel('chat.{roomId}', function (User $user, int $roomId) {
if ($user->canJoinRoom($roomId)) {
return ['id' => $user->id, 'name' => $user->name];
}
});
Приєднання до каналів присутності
Щоб приєднатися до каналу присутності, ви можете використовувати метод Echo join. Метод join поверне реалізацію PresenceChannel, яка, окрім надання методу listen, дозволяє підписуватися на події here, joining та leaving.
Echo.join(`chat.${roomId}`)
.here((users) => {
// ...
})
.joining((user) => {
console.log(user.name);
})
.leaving((user) => {
console.log(user.name);
})
.error((error) => {
console.error(error);
});
The here зворотний виклик буде виконано негайно після успішного приєднання до каналу, і він отримає масив, що містить інформацію про користувачів для всіх інших користувачів, які наразі підписані на канал. Метод joining буде виконано, коли новий користувач приєднується до каналу, тоді як метод leaving буде виконано, коли користувач залишає канал. Метод error буде виконано, коли кінцева точка автентифікації повертає HTTP статус-код, відмінний від 200, або якщо виникає проблема з розбором поверненого JSON.
Трансляція до каналів присутності
Канали присутності можуть отримувати події так само, як публічні або приватні канали. Використовуючи приклад чату, ми можемо захотіти транслювати події NewMessage до каналу присутності кімнати. Для цього ми повернемо екземпляр PresenceChannel з методу broadcastOn події:
/**
* Отримати канали, на яких подія повинна транслюватися.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PresenceChannel('chat.'.$this->message->room_id),
];
}
Як і з іншими подіями, ви можете використовувати хелпер broadcast і метод toOthers, щоб виключити поточного користувача з отримання трансляції:
broadcast(new NewMessage($message));
broadcast(new NewMessage($message))->toOthers();
Як і у випадку з іншими типами подій, ви можете прослуховувати події, що надсилаються на канали присутності, використовуючи метод Echo listen:
Echo.join(`chat.${roomId}`)
.here(/* ... */)
.joining(/* ... */)
.leaving(/* ... */)
.listen('NewMessage', (e) => {
// ...
});
Трансляція Моделей
Перш ніж читати наступну документацію про трансляцію моделей, ми рекомендуємо ознайомитися із загальними концепціями служб трансляції моделей Laravel, а також з тим, як вручну створювати та слухати трансляційні події.
Зазвичай події транслюються, коли ваші Eloquent моделі створюються, оновлюються або видаляються. Звісно, це можна легко здійснити, вручну визначивши власні події для змін стану Eloquent моделей і позначивши ці події інтерфейсом ShouldBroadcast.
Однак, якщо ви не використовуєте ці події для будь-яких інших цілей у вашому застосунку, може бути обтяжливо створювати класи подій лише з метою їх трансляції. Щоб вирішити цю проблему, Laravel дозволяє вказати, що модель Eloquent повинна автоматично транслювати зміни свого стану.
Щоб почати, ваша модель Eloquent повинна використовувати трейд Illuminate\Database\Eloquent\BroadcastsEvents. Крім того, модель повинна визначити метод broadcastOn, який повертатиме масив каналів, на яких події моделі повинні транслюватися:
<?php
namespace App\Models;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Database\Eloquent\BroadcastsEvents;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
use BroadcastsEvents, HasFactory;
/**
* Отримати користувача, якому належить пост.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* Отримати канали, на яких події моделі повинні транслюватися.
*
* @return array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>
*/
public function broadcastOn(string $event): array
{
return [$this, $this->user];
}
}
Як тільки ваша модель включає цю рису та визначає свої канали трансляції, вона почне автоматично транслювати події, коли екземпляр моделі створюється, оновлюється, видаляється, переміщується в кошик або відновлюється.
Крім того, ви могли помітити, що метод broadcastOn отримує аргумент-рядок $event. Цей аргумент містить тип події, яка відбулася з моделлю, і може мати значення created, updated, deleted, trashed або restored. Перевіряючи значення цієї змінної, ви можете визначити, на які канали (якщо такі є) модель повинна транслювати для конкретної події:
/**
* Отримати канали, на яких події моделі повинні транслюватися.
*
* @return array<string, array<int, \Illuminate\Broadcasting\Channel|\Illuminate\Database\Eloquent\Model>>
*/
public function broadcastOn(string $event): array
{
return match ($event) {
'deleted' => [],
default => [$this, $this->user],
};
}
Налаштування Створення Подій Трансляції Моделі
Іноді ви можете захотіти налаштувати, як Laravel створює базову подію трансляції моделі. Ви можете досягти цього, визначивши метод newBroadcastableEvent у вашій моделі Eloquent. Цей метод повинен повертати екземпляр Illuminate\Database\Eloquent\BroadcastableModelEventOccurred:
use Illuminate\Database\Eloquent\BroadcastableModelEventOccurred;
/**
* Створіть нову подію моделі, що транслюється, для моделі.
*/
protected function newBroadcastableEvent(string $event): BroadcastableModelEventOccurred
{
return (new BroadcastableModelEventOccurred(
$this, $event
))->dontBroadcastToCurrentUser();
}
Конвенції Трансляції Моделей
Конвенції каналів
Як ви могли помітити, метод broadcastOn у наведеному вище прикладі моделі не повертав екземпляри Channel. Натомість, безпосередньо поверталися моделі Eloquent. Якщо екземпляр моделі Eloquent повертається методом broadcastOn вашої моделі (або міститься в масиві, що повертається методом), Laravel автоматично створить екземпляр приватного каналу для моделі, використовуючи ім'я класу моделі та ідентифікатор первинного ключа як ім'я каналу.
Отже, модель App\Models\User з id 1 буде перетворена на екземпляр Illuminate\Broadcasting\PrivateChannel з ім'ям App.Models.User.1. Звичайно, окрім повернення екземплярів моделі Eloquent з методу broadcastOn вашої моделі, ви можете повертати повні екземпляри Channel, щоб мати повний контроль над іменами каналів моделі:
use Illuminate\Broadcasting\PrivateChannel;
/**
* Отримати канали, на яких події моделі повинні транслюватися.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(string $event): array
{
return [
new PrivateChannel('user.'.$this->id)
];
}
Якщо ви плануєте явно повертати екземпляр каналу з методу вашої моделі broadcastOn, ви можете передати екземпляр моделі Eloquent до конструктора каналу. При цьому Laravel використовуватиме конвенції каналу моделі, обговорені вище, щоб перетворити модель Eloquent у рядок імені каналу:
return [new Channel($this->user)];
Якщо вам потрібно визначити назву каналу моделі, ви можете викликати метод broadcastChannel на будь-якому екземплярі моделі. Наприклад, цей метод повертає рядок App.Models.User.1 для моделі App\Models\User з id 1:
$user->broadcastChannel();
Конвенції подій
Оскільки події трансляції моделі не пов'язані з "фактичною" подією в директорії App\Events вашого застосунку, їм призначається ім'я та дані на основі конвенцій. Конвенція Laravel полягає в трансляції події, використовуючи ім'я класу моделі (без урахування простору імен) та ім'я події моделі, яка викликала трансляцію.
Отже, наприклад, оновлення моделі App\Models\Post буде транслювати подію до вашого клієнтського застосунку як PostUpdated з наступним вмістом:
{
"model": {
"id": 1,
"title": "My first post"
...
},
...
"socket": "someSocketId"
}
Видалення моделі App\Models\User буде транслювати подію з назвою UserDeleted.
Якщо ви бажаєте, ви можете визначити власне ім'я трансляції та вміст, додавши методи broadcastAs та broadcastWith до вашої моделі. Ці методи отримують ім'я події/операції моделі, яка відбувається, дозволяючи вам налаштувати ім'я події та вміст для кожної операції моделі. Якщо з методу broadcastAs повертається null, Laravel використовуватиме угоди про імена подій трансляції моделі, обговорені вище, під час трансляції події:
/**
* Ім'я трансляції події моделі.
*/
public function broadcastAs(string $event): string|null
{
return match ($event) {
'created' => 'post.created',
default => null,
};
}
/**
* Отримати дані для трансляції моделі.
*
* @return array<string, mixed>
*/
public function broadcastWith(string $event): array
{
return match ($event) {
'created' => ['title' => $this->title],
default => ['model' => $this],
};
}
Прослуховування трансляцій моделей
Після того як ви додали трейд BroadcastsEvents до вашої моделі та визначили метод broadcastOn вашої моделі, ви готові почати слухати транслювані події моделі у вашому клієнтському застосунку. Перш ніж почати, можливо, ви захочете ознайомитися з повною документацією про прослуховування подій.
Спочатку використайте метод private для отримання екземпляра каналу, потім викличте метод listen для прослуховування вказаної події. Зазвичай, ім'я каналу, яке передається методу private, повинно відповідати конвенціям мовлення моделі Laravel.
Як тільки ви отримали екземпляр каналу, ви можете використовувати метод listen для прослуховування певної події. Оскільки події трансляції моделі не пов'язані з "фактичною" подією в директорії App\Events вашого застосунку, ім'я події повинно бути префіксоване з ., щоб вказати, що воно не належить до певного простору імен. Кожна подія трансляції моделі має властивість model, яка містить усі властивості моделі, що підлягають трансляції:
Echo.private(`App.Models.User.${this.user.id}`)
.listen('.UserUpdated', (e) => {
console.log(e.model);
});
Використання React або Vue
Якщо ви використовуєте React або Vue, ви можете скористатися включеним у Laravel Echo хуком useEchoModel, щоб легко слухати трансляції моделей:
import { useEchoModel } from "@laravel/echo-react"; useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => { console.log(e.model); });
<script setup lang="ts">
import { useEchoModel } from "@laravel/echo-vue";
useEchoModel("App.Models.User", userId, ["UserUpdated"], (e) => {
console.log(e.model);
});
</script>
Ви також можете вказати форму даних корисного навантаження події моделі, забезпечуючи більшу безпеку типів і зручність редагування:
type User = {
id: number;
name: string;
email: string;
};
useEchoModel<User, "App.Models.User">("App.Models.User", userId, ["UserUpdated"], (e) => {
console.log(e.model.id);
console.log(e.model.name);
});
Події клієнта
Коли ви використовуєте Pusher Channels, ви повинні увімкнути опцію "Client Events" у розділі "App Settings" на панелі керування застосунком, щоб надсилати події клієнта.
Іноді ви можете захотіти транслювати подію іншим підключеним клієнтам, не звертаючись до вашого Laravel застосунку взагалі. Це може бути особливо корисним для таких речей, як сповіщення про "набір тексту", коли ви хочете повідомити користувачів вашого застосунку, що інший користувач набирає повідомлення на певному екрані.
Щоб транслювати події клієнта, ви можете використовувати метод Echo whisper:
Echo.private(`chat.${roomId}`) .whisper('typing', { name: this.user.name });
import { useEcho } from "@laravel/echo-react"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().whisper('typing', { name: user.name });
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().whisper('typing', { name: user.name });
</script>
Щоб прослуховувати події клієнта, ви можете використовувати метод listenForWhisper:
Echo.private(`chat.${roomId}`) .listenForWhisper('typing', (e) => { console.log(e.name); });
import { useEcho } from "@laravel/echo-react"; const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => { console.log('Chat event received:', e); }); channel().listenForWhisper('typing', (e) => { console.log(e.name); });
<script setup lang="ts">
import { useEcho } from "@laravel/echo-vue";
const { channel } = useEcho(`chat.${roomId}`, ['update'], (e) => {
console.log('Chat event received:', e);
});
channel().listenForWhisper('typing', (e) => {
console.log(e.name);
});
</script>
Сповіщення
Поєднуючи трансляцію подій з сповіщеннями, ваш JavaScript-застосунок може отримувати нові сповіщення в міру їх появи без необхідності оновлювати сторінку. Перш ніж почати, обов'язково ознайомтеся з документацією щодо використання каналу трансляції сповіщень.
Після того як ви налаштували сповіщення для використання каналу трансляції, ви можете слухати події трансляції, використовуючи метод notification Echo. Пам'ятайте, що назва каналу повинна відповідати назві класу сутності, яка отримує сповіщення:
Echo.private(`App.Models.User.${userId}`) .notification((notification) => { console.log(notification.type); });
import { useEchoModel } from "@laravel/echo-react"; const { channel } = useEchoModel('App.Models.User', userId); channel().notification((notification) => { console.log(notification.type); });
<script setup lang="ts">
import { useEchoModel } from "@laravel/echo-vue";
const { channel } = useEchoModel('App.Models.User', userId);
channel().notification((notification) => {
console.log(notification.type);
});
</script>
У цьому прикладі всі сповіщення, надіслані до екземплярів App\Models\User через канал broadcast, будуть отримані зворотним викликом. Зворотний виклик авторизації каналу для каналу App.Models.User.{id} включено у файл routes/channels.php вашого застосунку.
