Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Middle: питання на співбесіді з теми «Трансляція подій»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

Broadcasting транслює серверні події на клієнт через WebSockets - для оновлень у реальному часі (чати, нотифікації).

class MessageSent implements ShouldBroadcast
{
    public function broadcastOn(): array
    {
        return [new PrivateChannel('chat.'.$this->roomId)];
    }
}

На клієнті Laravel Echo підписується на канал:

Echo.private(`chat.${roomId}`)
    .listen('MessageSent', (e) => console.log(e.message));

Сервер WebSockets - Laravel Reverb (офіційний), Pusher або Soketi. Канали бувають public, private (з авторизацією) і presence (зі списком учасників).

Докладніше в документації: Broadcasting

Канал присутності (presence channel) - приватний канал, який додатково знає, хто саме в ньому зараз. Ідеальний для чатів, спільного редагування, списку «зараз переглядають».

Авторизація відрізняється від звичайного приватного каналу: колбек повертає масив даних про користувача, а не true:

// routes/channels.php
Broadcast::channel('chat.{roomId}', function (User $user, int $roomId) {
    if ($user->canJoinRoom($roomId)) {
        return ['id' => $user->id, 'name' => $user->name];
    }
});

Ці дані побачать усі учасники каналу - не повертайте туди email, телефони чи інші приватні поля.

Приєднання на фронтенді:

Echo.join(`chat.${roomId}`)
    .here((users) => { online.value = users; })          // хто вже в каналі
    .joining((user) => { online.value.push(user); })      // хтось прийшов
    .leaving((user) => { remove(user); })                 // хтось пішов
    .listen('NewMessage', (e) => { messages.value.push(e.message); });

Клієнтські події (whisper) - повідомлення від одного клієнта іншим без звернення до Laravel:

// відправник
Echo.private(`chat.${roomId}`).whisper('typing', { name: user.name });

// отримувачі
Echo.private(`chat.${roomId}`).listenForWhisper('typing', (e) => {
    showTyping(e.name);
});

Застосунок не бачить цих повідомлень, тому:

  • whisper - лише для ефемерних, неважливих сигналів: «набирає», курсор співрозмовника, «переглядає зараз»;
  • нічого, що має зберігатися чи перевірятися (повідомлення чату, зміни даних), через whisper не йде - тільки через HTTP-запит до застосунку, який валідує, зберігає й транслює подію;
  • whisper працює лише в приватних каналах і каналах присутності; у Pusher клієнтські події треба окремо увімкнути в налаштуваннях застосунку.

toOthers() - щоб відправник не отримав власну подію повторно:

broadcast(new NewMessage($message))->toOthers();

Echo автоматично додає заголовок X-Socket-ID до запитів, і Laravel виключає це з'єднання з отримувачів.

Нюанси: користувач з двома вкладками - два з'єднання, але в списку присутності він один (учасники об'єднуються за id). Події leaving приходять із затримкою при обриві мережі - сервер виявляє мертве з'єднання не миттєво.

Докладніше в документації: Broadcasting: канали присутності