Junior: питання на співбесіді з теми «Трансляція подій»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
2 питання
Звичайний вебзастосунок відповідає лише на запит: сторінка оновиться тоді, коли її оновить користувач. Бродкастинг дозволяє серверу самому надіслати повідомлення у відкритий браузер - без перезавантаження й без опитування.
Навіщо: чат, сповіщення, лічильник онлайн, прогрес довгого завдання, оновлення списку без кнопки «оновити».
Як це виглядає. Подія позначається інтерфейсом:
class VacancyPublished implements ShouldBroadcast
{
public function __construct(public Vacancy $vacancy)
{
}
public function broadcastOn(): Channel
{
return new Channel('vacancies');
}
}
Далі звичайне VacancyPublished::dispatch($vacancy) - і подія йде не лише слухачам на сервері, а й у браузер.
На клієнті її слухає Echo:
Echo.channel('vacancies')
.listen('VacancyPublished', (e) => {
console.log(e.vacancy.title);
});
Що потрібно, крім коду: окремий сервіс, який тримає WebSocket-зʼєднання - Laravel Reverb (власний), Pusher чи Ably. PHP-процес сам зʼєднання не тримає.
Альтернатива, про яку варто памʼятати. Якщо оновлення рідкісні або потрібні лише одному користувачеві, звичайне опитування раз на кілька секунд чи wire:poll у Livewire простіші й не вимагають окремого сервера. Бродкастинг виправданий, коли подій багато, вони мають доходити миттєво й до багатьох одразу.
Reverb - власний WebSocket-сервер Laravel, написаний на PHP. Він замінює сторонні сервіси на кшталт Pusher чи Ably: замість платити за кількість з'єднань і повідомлень, ви запускаєте сервер на своїй інфраструктурі.
Reverb реалізує протокол Pusher, тому фронтенд працює зі звичним Laravel Echo і клієнтом pusher-js, а перехід з Pusher на Reverb (чи назад) - це зміна змінних оточення.
Встановлення:
php artisan install:broadcasting --reverb
Команда встановлює пакети Composer і NPM, публікує конфігурацію, створює routes/channels.php і додає в .env ключі:
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=...
REVERB_APP_KEY=...
REVERB_APP_SECRET=...
REVERB_HOST=localhost
REVERB_PORT=8080
Запуск сервера:
php artisan reverb:start
php artisan reverb:start --debug # показувати вхідні й вихідні повідомлення
Подія для трансляції:
class OrderShipped implements ShouldBroadcast
{
public function __construct(public Order $order) {}
public function broadcastOn(): array
{
return [new PrivateChannel('orders.' . $this->order->user_id)];
}
}
Прослуховування на фронтенді:
Echo.private(`orders.${userId}`).listen('OrderShipped', (e) => {
console.log(e.order);
});
Що важливо пам'ятати:
ShouldBroadcastвідправляє подію через чергу - без запущеного воркера повідомлення не надходять.ShouldBroadcastNow- одразу, без черги;REVERB_SERVER_HOST/REVERB_SERVER_PORT- де слухає сам сервер, аREVERB_HOST/REVERB_PORT- куди Laravel надсилає повідомлення. На продакшені Reverb зазвичай слухає0.0.0.0:8080, а назовні доступний через Nginx на443;- Reverb - довгоживучий процес: після деплою його треба перезапустити (
reverb:restart), а на сервері тримати під Supervisor.