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 (зі списком учасників).
Канал присутності (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 приходять із затримкою при обриві мережі - сервер виявляє мертве з'єднання не миттєво.